chevron-thin-right chevron-thin-left brand cancel-circle search youtube-icon google-plus-icon linkedin-icon facebook-icon twitter-icon toolbox download check linkedin phone twitter-old google-plus facebook profile-male chat calendar profile-male
Welcome to Typemock Community! Here you can ask and receive answers from other community members. If you liked or disliked an answer or thread: react with an up- or downvote.
0 votes
Hi

I am trying to fake a method that as an argument receives a ref parameter that is a struct:

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using TypeMock.ArrangeActAssert;

namespace TestProject1
{
    public struct Result
    {
        public int Value;
    }
    
    [TestClass]
    public class ProgramTest
    {
        public static void Method(ref Result r)
        {
            r.Value = 1;
        }

        [TestMethod]
        [Isolated]
        public void MethodTest()
        {
            // Arrange
            var r = new Result {Value = 123};

            Isolate.WhenCalled(() => Method(ref r)).
                DoInstead(context =>
                              {
                                  var r2 = (Result) context.Parameters[0];
                                  r2.Value = 321;
                              });

            // Act
            Method(ref r);

            // Assert
            Assert.AreEqual(321, r.Value);
        }
    }
}


My DoInstead block is called, by the Value isn't changed on r - hence the Assert fails unexpectedly. If I change Result to a class it is working perfectly - but fails if its a struct.

Is this a bug? and are there any workarrounds?
asked by ahvam (1.7k points)

4 Answers

0 votes
Hi,

The issue you presented is interesting.

Since the parameters are passed threw the context object the code must cast it for usage. The moment you cast and assign to variable the struct is copied and it's no longer reference.

In this example 'result' is not the same as context.Parameters[0]
Result result = (Result) context.Parameters[0];


Could you please describe the wider problem domain you're in? Maybe we can find a workaround to the problem.

Best Regards,
Elisha
Typemock Support Team
answered by Elisha (12k points)
0 votes
Of course, thanks. Doing it like this will work:

object r2 = context.Parameters[0];
ObjectState.SetField(r2, "Value", 321);
answered by ahvam (1.7k points)
0 votes
Hm, when I am using the NonPublic.WhenCalled I get a different behavior. This fails:

            Isolate.NonPublic.WhenCalled(typeof(ProgramTest), "Method").
            // Isolate.WhenCalled(() => Method(ref r)).
                DoInstead(context =>
                              {
                                  var r2 = context.Parameters[0];
                                  ObjectState.SetField(r2, "Value", 321);
                              });


Maybe NonPublic.WhenCalled makes a copy of the struct, and WhenCalled dosn't?
answered by ahvam (1.7k points)
0 votes
Hi,

Thanks for making the case clear. This case is a bug and it will be fixed in a future version.

Best Regards,
Elisha
Typemock Support Team
answered by Elisha (12k points)
...