Moq fake one method but use real implementation of another

30,479

Solution 1

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

Solution 2

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.

Share:
30,479

Related videos on Youtube

Sam Leach
Author by

Sam Leach

C# and JavaScript

Updated on September 30, 2020

Comments

  • Sam Leach
    Sam Leach over 3 years

    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.

  • Jeppe Stig Nielsen
    Jeppe Stig Nielsen over 10 years
    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<MyNetworkStream>?
  • Sam Leach
    Sam Leach over 10 years
    @JeppeStigNielsen, no I don't think you can. In my case both my methods are coming from an abstract class.
  • vijay
    vijay over 4 years
    You mean ? var mock = new Mock<INetworkStream>(){ CallBase = true };
  • TDao
    TDao over 2 years
    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.