测试是否使用不同的参数调用了两次方法

Testing whether a method was called twice with different arguments

我需要验证某个方法是否已使用特定参数调用了 2 次:

public void Execute()
{
    Counter с = new Counter(1);
    
    // Basically, I need to verify that DoSomething method was called twice: 
    // First time with an argument, which internal value is 1... 
    _subject.DoSomething(с);
    
    c.Increment();
    
    // ... and the second time - with internal value of 2
    _subject.DoSomething(c);
}

这是我的验证部分,两个断言都失败了:

// Fails with message "Expected invocation on the mock once, but was 0 times" 
mock.Verify(
    m => m.DoSomething(
        It.Is<Counter>(
            x => x.GetValue() == 1
        )
    ), 
    Times.Once
);

// Fails with message "Expected invocation on the mock once, but was 2 times" 
mock.Verify(
    m => m.DoSomething(
        It.Is<Counter>(
            x => x.GetValue() == 2
        )
    ), 
    Times.Once
);

所以问题是 Execute 方法中的两次调用都使用相同的参数,在执行断言时它包含 2 作为其内部值。

问题是如何让 mock 以某种方式“记录”参数,以便正确评估它们?

下面是完整列表:

[Test]
public void CheckSomething()
{
    Mock<Subject> mock = new Mock<ISubject>();
    mock.Setup(m => m.DoSomething(It.IsAny<Counter>()));
    var myService = new MyService(mock.Object);

    myService.Execute();

    mock.Verify(m => m.DoSomething(It.Is<Counter>(x => x.GetValue() == 2)), Times.Once);
    mock.Verify(m => m.DoSomething(It.Is<Counter>(x => x.GetValue() == 1)), Times.Once);
}

public interface ISubject
{
    public void DoSomething(Counter с);
}

public class Subject : ISubject
{
    public void DoSomething(Counter с)
    {
        // doesn't matter
    }
}

public class MyService
{
    private readonly ISubject _subject;

    public MyService(ISubject subject)
    {
        _subject = subject;
    }

    public void Execute()
    {
        Counter с = new Counter(1);
        _subject.DoSomething(с);
        с.Increment();
        _subject.DoSomething(с);
    }
}

public class Counter
{
    private int _val;

    public Counter(int val)
    {
        _val = val;
    }

    public void Increment()
    {
        _val++;
    }

    public int GetValue()
    {
        return _val;
    }
}


非常感谢任何反馈,谢谢!

您可以在设置 DoSomething 时设置回调以跟踪计数器值的增量。

int counterEqual1 = 0;
int counterEqual2 = 0;

mock.Setup(m => m.DoSomething(It.IsAny<Counter>()))
    .Callback<Counter>(counter =>
    {
        if (counter.GetValue() == 1)
            counterEqual1++;
        else if (counter.GetValue() == 2)
            counterEqual2++;
    });

然后验证这些调用:

mock.Verify(m => m.DoSomething(It.IsAny<Counter>()), Times.Exactly(2));
Assert.That(counterEqual1, Is.EqualTo(1));
Assert.That(counterEqual2, Is.EqualTo(1));