5
votes

I have a dependency that I would like to mock.

public abstract class MyDependency
{
    protected Dictionary<string, object> _outputs = new Dictionary<string, object>();
    public Dictionary<string, object> Outputs
    {
        get
        {
            return _outputs;
        }
    }
}

I need the public property Outputs to return a known value for the purpose of my unit test. I know that we cannot mock fields or non-virtual members. So, I could go and create my own mocked MyDependency that sets the backing field _outputs:

public class MockMyDependency : MyDependency
{
    public MockMyDependency()
    {
        _outputs = new Dictionary<string, object>
        {
            { "key", "value" }
        };
    }
}

However, is it possible to use Moq to do this without explicitly creating my own derived mock class?

4
Does SetupGet() work on abstract classes? - 48klocs
@48klocs Yes, but to properly mock a property (or method), that property would have to be marked as abstract or virtual. Unfortunately, I am not able to modify the MyDependency class. - Stephen Booher
suggested edit: "for properties" in title, not fields, as the question and answers concern. - Robert Mock

4 Answers

4
votes

If you cannot change the property to be virtual or define an interface (I assume if you can't do the first one you won't be able to do the second one either) then I see only two possible options:

  • Use a mocking framework that does support mocking of non virtual members (e.g. TypeMock)
  • Create a specific mock implementation that inherits from MyDependency as you already did.
2
votes

If you don't derive from the class yourself, it's pretty hard to specify the protected field _outputs because it's not in scope and its name will not compile.

But you can do it with nasty reflection of course:

var mock = new Mock<MyDependency>();

var field = typeof(MyDependency)
    .GetField("_outputs", BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(mock.Object,
    new Dictionary<string, object> { { "key", "value" } });

If you do derive from MyDependency after all, then inside the class that derives from it, you can set the field directly, as in:

// this code is inside some class which derives from MyDependency
mock.Object._outputs = new Dictionary<string, object> { { "key", "value" } };
1
votes

I think I understand what you are asking, I think you are looking for something like this:

public class Test
{
    public void MockObject()
    {
        var mocked = new Moq.Mock<MyDependency>();
        mocked.CallBase = true;
        mocked.Setup(m => m.Outputs).Returns(new Dictionary<string, object>() { { "key", "value" } });

        mocked.Object.{do something with mocked object};
    }
}

... I think you will still need a virtual on the Outputs property though.

1
votes

Declare an interface that exposes the members you want from the MyDependency class, you can then use this with Moq to create the behaviour you need for your tests.

public interface IMyDependency {
    Dictionary<string, object> Outputs { get; }
}

// test...
var dictionary = new Dictionary<string, string>{{"key", "value"}};
var dependency = new Mock<IMyDependency>();
dependency.SetupGet(d => d.Outputs).Returns(dictionary);

When you come to use it in your production code, you can "cast" MyDependency instances in behind your interface using DuckTyping (or similar).