3
votes

while mocking an object using parametrized constructor, if the property being initialized within the constructor is virtual, Moq does not set property value. But if it is non-virtual property, Moq sets the value.

Following is my class I wants to mock.

public class Activity
{
    private Activity() {}
    public Activity(string code, string description, string option)
    {
        if(string.IsNullOrEmpty(code)) throw  new ArgumentNullException("code");
        if (string.IsNullOrEmpty(option)) throw new ArgumentNullException("option");

        Code = code;
        Description = description;
        Option = option;
    }

    public virtual string Code { get; private set; }
    public virtual string Description { get; private set; }
    public virtual string Option { get; private set; }

}

This is how I try to mock it:

    [TestMethod]
    public void It_Creates_Mock_For_A_Class()
    {
        var mock = new Mock<Activity>("Code 1", null, "Option");
        Assert.IsNotNull(mock.Object);
        Assert.AreEqual("Code 1", mock.Object.Code);
    }

The test method fails saying: Assert.AreEqual failed. Expected:. Actual:<(null)>.

But if I remove the virtual keyword from all the property, it works and passes the test case.

I have to keep the properties virtual because of Entity Framework.

Any clue? How to get around this problem?

1
Actually your test tests MOQ framework instead of testing your implementation of constructor. What do you want to test? Do you ask about strange MOQ behaviour only?Ilya Palkin
@IlyaPalkin Above was just an example to demonstrate the problem I was facing with Moq in case of virtual/non-virtual property. Due to this problem many of the behavioural test cases I was trying to write were failing, as internally the private methods of the Activity Class uses these properties and finding them null.101V

1 Answers

3
votes

Found out that if "CallBase" property is set to true, it solved the problem.

By looking at the assembly in Object Browser, the summary says:

Summary: Whether the base member virtual implementation will be called for mocked classes if no setup is matched. Defaults to false.

The code that works:

    [TestMethod]
    public void It_Creates_Mock_For_A_Class()
    {
        var mock = new Mock<Activity>("Code 1", null, "Option");
        mock.CallBase = true;
        Assert.IsNotNull(mock.Object);
        Assert.AreEqual("Code 1", mock.Object.Code);
    }