Search code examples
unit-testingc#-4.0tddmoqmoq-3

Moq: Can I swap between mocked member/property behavior and unmocked member/property behavior?


I want to use one instance of a mock library I am using in a test class, however, for some tests, I may want to mock one of the member functions to do/return mocked behavior/returned value; for other tests, I may want the unmocked (native) functionality of the library. Is there a way to swap between Setup in one instance (mocked behavior), and "UNSetup" (unmocked behavior) in another?


Solution

  • There isn't any built-in mechanism to do that, but partial mocks kind of let you do the same (with some limitations). Parial mock allows you to mock concrete implementation of the interface as opposed to interface alone, like this:

    var partialMock = new Mock<ServiceImplementation>();
    

    Limitations are that all the methods you possibly want to mock need to be virtual, otherwise Moq cannot intercept them:

    public class ServiceImplementation
    {
        public virtual int SomeMethod()
        {
            return 5;
        }
    
        public virtual int SomeOtherMethod()
        {
            return SomeMethod()*2;
        }
    }
    
    
    var partialMock = new Mock<ServiceImplementation>();
    // we stub one method
    partialMock.Setup(m => m.SomeMethod()).Returns(3);
    // and use other's real implementation
    var value = partialMock.Object.SomeOtherMethod();
    

    Problem of course lies in the virtuality; in case you can't make your members virtual this obviously won't work. There's minor workaround though - use real implementation as parts of stub setup:

    // note we base our stub on interface now
    var implementation = new ServiceImplementation();
    var mock = new Mock<IServiceImplementation>();
    // we call real implementation as part of return setup
    mock.Setup(m => m.SomeMethod()).Returns(implementation.SomeMethod());