How to check that a call to any overload must have happened with FakeItEasy?
Asked Answered
S

1

6

I have a method which I am testing. Given certain inputs, it should write a failure method to the logger (an ILogger). The interface has several overloads for Log(), as well as some properties (ex. a logging level). I am mocking the logger using FakeItEasy.

What I want to assert is that a call to Log() has happened. However, I don't care about which specific overload got used. How can I do this?

My ideas:

// Doesn't work, since a different overload (with more parameters) is used.
A.CallTo(() => mockLogger.Log(null)).WithAnyArguments().MustHaveHappened();

// "Works", but if the code were to call something else on the logger
// (ex. change the logging level), this would also pass!
Any.CallTo(mockLogger).MustHaveHappened();
Shaving answered 9/3, 2011 at 15:3 Comment(1)
One way of resolving this is to not have overloads on your interface. Consider having one method that takes all the parameters and then provide all the "overloads" as extension methods on the interface. This helps both in testing but more importantly it makes it a lot easier for implementors of the interface.Sine
H
6

Edit

This can be done using the following syntax:

A.CallTo(logger).Where(x => x.Method.Name == "Log").MustHaveHappened()

Original answer

There's no easy way of doing that, and - correct me if I'm wrong - I don't think there is in any mocking framework.

That being said there is a - not so easy - way to do it provided in the example below.

public interface ILogger
{
    void Log(string value);
    void Log(object value);
}

public class LoggerTests
{
    public void FakeGetCallsExample()
    {
        var logger = A.Fake<ILogger>();

        logger.Log("whatever");

        var callsToLog = Fake.GetCalls(logger).Where(x => x.Method.Name.Equals("Log"));

        // Asserting with NUnit.
        Assert.That(callsToLog(), Is.Not.Empty);
    }

    // The following does not work as of now but I'll seriously consider
    // implementing it:
    public void AnyCallToWithCallSpecificationExample()
    {
        var logger = A.Fake<ILogger>();

        logger.Log("whatever");

        // I would add a "filtering" method to the Any.CallTo-syntax:
        Any.CallTo(logger).WhereCallMatches(x => x.Method.Name.Equals("Log")).MustHaveHappened();

        // It would also enable an extension method:
        Any.CallTo(logger).ToMethodNamed("Log").MustHaveHappened();
    }
}
Hernando answered 14/3, 2011 at 18:53 Comment(1)
I solved it locally as in your comment above, i.e. by having only one method with all parameters and other convenience overloads via extension methods.Shaving

© 2022 - 2024 — McMap. All rights reserved.