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
0 votes
The situation is a bit complicated to explain so I'll simply provide a code example. Essentially, setting an expected return value on the property of an object that is set to ReturnRecursiveFake() will impact the value of the variable being set in the WillReturn.

[TestClass]
public class TestUriSideEffect
{
    [TestMethod, Isolated]
    public void Test()
    {
        // ARRANGE
        var scope = new Uri("Folder/", UriKind.Relative);
        Assert.AreEqual("Folder/", scope.ToString());

        var something = new SomeClass();
        Isolate.WhenCalled(() => something.Something).ReturnRecursiveFake();

        // ACT
        Isolate.WhenCalled(() => something.Something.Scope).WillReturn(scope);

        // ASSERT
        Assert.AreEqual("Folder/", scope.ToString());
    }

    public class SomeClass
    {
        public ISomething Something { get; private set; }
    }

    public interface ISomething
    {
        Uri Scope { get; }

        void Something();
    }
}
asked by Christian.Merat (2.9k points)

3 Answers

0 votes
Hi Christian,

This happens because of the line:
Isolate.WhenCalled(() => something.Something).ReturnRecursiveFake();

When you use the ReturnRecursiveFake API that means that every object that is returned from the from the faked instance will also have a recursive fake behavior.

Please let me know if it helps.
answered by ohad (35.4k points)
0 votes
Sorry to necro this thread, I tried to reply to your post many times over the past months but the forums were always broken (couldn't log in). Anyways, login works now so here's my response.

The problem isn't that "something.Something.Scope" is returning a recursive fake -- that is exactly what I expect it to do. The problem is that since I did "WillReturn(scope)", the TypeMock engine is modying the scope variable as a side-effect. You'll notice that my 2nd assert - the one that throws an exception - is on the variable itself which is not mocked.
answered by Christian.Merat (2.9k points)
0 votes
Hi,

You're right, this is a bug. I'm investigating it and hope to provide a fix soon.

As a first workaround you can replace the initialization of scope with:
var scope = Isolate.Fake.Instance<Uri>(Members.CallOriginal, ConstructorWillBe.Called, "Folder/", UriKind.Relative);

This is the same as initializing the instance by itself, but Isolator is introduced with the instance as early.

As a second workaround, you can split the the first fake statement:
[TestMethod, Isolated]
public void Test()
{
    // ARRANGE
    var scope = new Uri("Folder/", UriKind.Relative);
    
    Assert.AreEqual("Folder/", scope.ToString());

    var something = new SomeClass();
    var fakeSomething = Isolate.Fake.Instance<ISomething>();
    Isolate.WhenCalled(() => something.Something).WillReturn(fakeSomething);

    // ACT
    Isolate.WhenCalled(() => fakeSomething.Scope).WillReturn(scope);

    // ASSERT
    Assert.AreEqual("Folder/", scope.ToString());
}


I'll update on this thread when a fix is available.

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