#c# #moq
Вопрос:
Мне нужно убедиться, что метод был вызван 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 в качестве своего внутреннего значения.
Вопрос в том, как сделать макет, чтобы каким-то образом «записать» аргументы, чтобы они были правильно оценены?
Ниже приведен полный список:
[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;
}
}
Я действительно ценю любую обратную связь, спасибо!
Ответ №1:
Вы можете установить обратный вызов при настройке 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));