devlooped / moq

The most popular and friendly mocking framework for .NET
Other
5.94k stars 802 forks source link

Verify() with custom failure message #650

Closed mpdelbuono closed 6 years ago

mpdelbuono commented 6 years ago

When using Verifiable() setups, a call to Verify() is used without any parameters to verify that the expected calls were made. However, sometimes I would like to put a custom failure message to include some extra data (for example, a RNG seed that generated the data for the test).

The other overloads of Verify() support a failMessage parameter, but there does not appear to be any Verify(string failMessage) which would be used for tests that use Verifiable().

It would be nice if we could add this in. (When I find some free time I might just implement this and make a PR for this, but I wanted to at least get some thoughts on it first, because perhaps there's a reason this is missing.)

stakx commented 6 years ago

If I understand you correctly, you would like to inject additional information not specific to any one particular setup into the verification error message, and the proposed Verify(string failMessage) would be the means to do just that. Correct?

I don't think that this functionality has to be provided by Moq. The unit testing framework of your choice likely already gives you the means to log additional information per test:

In my opinion it would be preferable to just use these mechanisms instead of reinventing the wheel in Moq. While mock.Verify(string failMessage) would seem a logical addition that "completes" the current API, keep in mind that the likely use case for setup.Verifiable(string failMessage) is to make it easier for you to identify that particular setup in cases where your test has a great number of similar setups. A mock.Verify(string failMessage) won't provide the same benefit.

Example for xUnit.net and Visual Studio:

using Moq;
using Xunit;
using Xunit.Abstractions;

public interface IFrobbler
{
    void Frobble();
}

public class Tests
{
    private ITestOutputHelper log;

    public Tests(ITestOutputHelper log)
    {
        this.log = log;
    }

    [Fact]
    public void FailingTest()
    {
        this.log.WriteLine("(Random number generator seed goes here.)");

        var mock = new Mock<IFrobbler>();
        mock.Setup(m => m.Frobble());
        mock.VerifyAll();
    }
}

failed-test-1

failed-test-2

mpdelbuono commented 6 years ago

I did not realize there was a setup.Verifiable(string failMessage) :)

Your argument that setup-specific probably makes more sense. While in my case I would have the same information for each Verifiable() call, I think my case is unusual. setup.Verifiable(string failMessage) works for me.

stakx commented 6 years ago

To be clear, I wasn't saying that you should use setup.Verifiable(failMessage) for general logging of any useful error information. I was saying that this particular method is useful to make setups more easily identifiable, and that you should use your testing framework's facilities for general logging.

I'm glad you found a solution that works for you. I'll close this then.