This is continuation of my previous post about mocking a constructor, but I think it deserves a new post with a new name, because this is in fact not about mocking a constructor, but about swapping arguments in a call to an object constructor. Let's see we have a simple class:
public class MyClass
{
public string A;
public string B;
public MyClass(string a, string b)
{
A = a;
B = b;
}
public string Concat()
{
return A + B;
}
}
What I need to in the test is to a create an instance of MyClass with arguments "e" and "f" passed to a constructor. Let's say it's difficult to establish test environment where "e" and "f" are passed during the test, so I want to swap arguments that are sent to a constructor.
First, if I simply mock the constructor then its fields will not be assigned at all, this is how it should be:
using (RecordExpectations recorder = new RecordExpectations())
{
theClass = new MyClass("e", "f");
}
theClass = new MyClass("a", "b");
Assert.IsNull(theClass.A);
Assert.IsNull(theClass.B);
So I am trying to use what Eli suggested yesterday: swap arguments using CheckArguments call:
using (RecordExpectations recorder = new RecordExpectations())
{
theClass = new MyClass("c", "d");
recorder.CheckArguments(new Assign("e"), new Assign("f"));
}
theClass = new MyClass("a", "b");
// This will fail! Fields are still null!!!
Assert.AreEqual("e", theClass.A);
Assert.AreEqual("f", theClass.B);
But it does not work! As you see in the code comments above, fields are not assigned even after a call to CheckArguments.
The only thing that I found working was not using natural mocks and calling ExpectUnmockedConstructor:
Mock theMock = MockManager.Mock(typeof(MyClass));
theMock.ExpectUnmockedConstructor().Args(new Assign("e"), new Assign("f"));
theClass = new MyClass("a", "b");
Assert.AreEqual("e", theClass.A);
Assert.AreEqual("f", theClass.B);
Assert.AreEqual("ef", theClass.Concat());
So at least there is a workaround not using natural mocks. But I would like to use it with RecordExpectations. Is this possible?