54

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.

Sam Leach
  • 12,746
  • 9
  • 45
  • 73

2 Answers2

80

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).

Sam Leach
  • 12,746
  • 9
  • 45
  • 73
Sunny Milenov
  • 21,990
  • 6
  • 80
  • 106
  • 7
    If the class `MyNetworkStream` implements `Method1` by a public method which does *not* have the `virtual` (or `abstract` or `override`) modifier, can you still setup this `Method1` on a `Mock`? – Jeppe Stig Nielsen Sep 29 '13 at 07:58
  • 4
    @JeppeStigNielsen, no I don't think you can. In my case both my methods are coming from an abstract class. – Sam Leach Sep 30 '13 at 07:46
  • You mean ? var mock = new Mock(){ CallBase = true }; – vijay Aug 22 '19 at 12:02
  • 1
    this only works if the methods are virtual in the class. I think OP want to mock the interface that the class inherits from, without modifying the class implementation to make the methods virtual. – TDao Dec 13 '21 at 04:08
11

In this case (unless there's a lot more going on) I would just create my own test class extending the class with the real behavior, that implements the interface you need to mock. This way you can mock the one value, and fallback to the base class for the real functionality.

Chris Missal
  • 5,987
  • 3
  • 28
  • 46