Search code examples
c#.netunit-testingnunitmoq

Moq fake one method but use real implementation of another


Given an interface IService that has Method1() and Method2().

I want to test that when Method1() throws an Exception, Method2() is called and returns a given value.

(Method2() is called when Method1() throws).

Therefore I need to test a real Method2() with a fake Method1(), they are methods of the same interface.

Here is my test code:

MBase sut.MethodX() is the only entry point. It uses IService.

My aim is to assert that Method2() returns something.

// Arrange
// Fake bytes in.
var networkStreamMock = new Mock<INetworkStream>();
networkStreamMock.Method1(x => x.Read(It.IsAny<byte[]>(), It.IsAny<int>(), It.IsAny<int>())).Returns(It.IsAny<byte[]>());

// Force throw TimeoutException.
var mock = new Mock<IService>();
mock.Setup(x => x.Method1(new Message
{ 
    Xml = Xml,  
}
)).Throws<TimeoutException>();

// Check Method 2 is called. (this is done in its own test so commented out)
// mock.Setup(m => m.Method2(It.IsAny<Message>())).Verifiable();

// New MBase.
IKernel kernel = new StandardKernel(new FakeBindings());
kernel.Rebind<IService>().ToConstant(mock.Object);
MBase sut = kernel.Get<M>();

// Act
sut.MethodX(networkStreamMock.Object);

// Here I would like to assert on the return value of Method2
mock.Verify(m => m.Method2(It.IsAny<Message>()));

Is this possible with Moq or another mocking framework? How do I do it? I can create a manual mock with a fake implementation of Method1() and a real implementation of Method2() but I wonder if there is a better approach.

I have already tested IService in isolation but I now wish to test it's interaction with MBase.


Solution

  • You can do this with:

    var mock = new Mock<MyNetworkStream>(){ CallBase = true };
    mock.Setup(m => m.Method1....
    

    The above code will use the real implementation of MyNetworkStream for any method/property which is not explicitly setup. I.e. it'll call the real Method2(), while the Method1() will be the mocked version.

    CallBase=true is usually meant to test abstract classes (if this is right or wrong, is out of the scope of this question).