Search code examples
c#moqxunit.net

Is there a way to delegate a mock implementation to an actual class without having to setup every method?


Let's say I have an interface I want to mock, and a concrete class that implements that interface, and I want to be able to verify that the mock is called (easy), but delegate the implementation without having to do setup on every parameter of every method call -- is there an easier way to do this?

[Fact]
public void CheckCalcImpl()
{
    var mockCalc = new Mock<ICalculator>();
    var mock = mockCalc.Object;
    var calc = new Calculator();
    mockCalc.Setup(mockCalc => mockCalc.Add(It.IsAny<int>(), It.IsAny<int>()))
        .Returns((int a, int b) => calc.Add(a, b));

    // pretend this is somewhere deep in another method and I want to verify it occurred, but I don't
    // want to setup every method on the ICalculator mock
    var result = mock.Add(1, 2);

    mockCalc.Verify(mockCalc => mockCalc.Add(It.IsAny<int>(), It.IsAny<int>()), Times.Once);
}

I looked at all the methods on the mock and didn't see what I was looking for... is there something else hidden away or in another useful library I can add to help me do this?


Solution

  • For something like this, I'd consider a Decorator-based Test Spy:

    public sealed class CalculatorSpy : ICalculator
    {
        private readonly ICalculator inner;
    
        public CalculatorSpy(ICalculator inner)
        {
            this.inner = inner;
            AddCalls = new List<(int, int)>();
        }
    
        public List<(int, int)> AddCalls { get; set; }
    
        // ICalculator members
        public int Add(int x, int y)
        {
            AddCalls.Add((x, y));
            return inner.Add(x, y);
        }
    
        // More members here...
    }
    

    Indeed, this may look a little more involved than doing the same with Moq, but it follows the DRY principle. You only need to implement and maintain this class once, instead of in each and every test case, so it's much more maintainable.