Tengiz
Tengiz

Reputation: 8399

Moq - Check whether method is mocked (setup-ed)

We all know that in Moq, we can mock the method using Setup. How can I check if the method is being setup? I don't want to invoke the method and check its result, because that will count during Verify as an actual call to the mocked method (unless you can tell me how to make that not count - that will also count as an answer).

Upvotes: 4

Views: 1973

Answers (2)

Oleg Skripnyak
Oleg Skripnyak

Reputation: 311

There is a very dirty method with reflection, but it works.

using System.Linq;
using System.Linq.Expressions;
using Moq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;

public static class MoqExtensions
{
    public static bool WasMethodSetup(this Mock mock, string method)
    {
        var moqSetups = new PrivateObject(new PrivateObject(mock).GetProperty("Setups")).Invoke("ToArray") as object[];
        var moqExpressions = moqSetups.Select(s => new PrivateObject(s).GetProperty("SetupExpression") as LambdaExpression);
        return moqExpressions.Where(e => e.Body.NodeType == ExpressionType.Call)
                .Select(b => new PrivateObject(new PrivateObject(b.Body).GetProperty("Method")).GetProperty("Name"))
                .Contains(method);
    }
}

Example of usage

var mock = new Mock<IDisposable>();
mock.Setup(d => d.Dispose());
var b1 = mock.WasMethodSetup("Dispose"); // true
var b2 = mock.WasMethodSetup("666"); // false

There is a problem when an unit test class do subclass another one, and tests of the subclass are already setup with subclass mocks. So there is only way to solve this problem is to setup subclass mocks to callback YOUR mock methods. Its.Ok(), but sometimes in your callbacks workflow it should be redirected to original mock method callback. Just searching how to invoke it from this mock list

Upvotes: 1

Tengiz
Tengiz

Reputation: 8399

Actually, I just found ResetCalls method defined on Mock, which will reset the counter. That may help me, since I can call the parent method and compare the result with the expected result. If the method returns null, then I setup since it wasn't done yet, then I reset the counter by calling ResetCalls (as if I never checked the result of the method). Then I continue with the child setup.

I need to watch for its side effects, but posting here in case somebody else has the same question. I still hope to find a better answer, such as maybe to reset the last call only to the mocked method. My current finding resets all the calls, which may not be what I want in all situations.

Upvotes: 1

Related Questions