为什么使用非内联It.IsAny<;T>;Moq无法正常工作
本文关键字:Moq 常工作 工作 gt It IsAny 为什么 lt | 更新日期: 2023-09-27 18:21:48
将It.IsAny<T>()
分配给变量以在模拟对象的Setup
中使用不会按预期工作:下面显示的测试失败。
但是,如果我内联anyString
变量,测试就会通过。这是怎么回事?
public class MyService
{
private readonly IDependency _dependency;
public MyService(IDependency dependency)
{
_dependency = dependency;
}
public string UseTheDependency(string input)
{
return _dependency.GetValue(input);
}
}
public interface IDependency
{
string GetValue(string input);
}
public class Tests
{
[Test]
public void TestTheTestClass()
{
var mockDependency = new Mock<IDependency>();
var anyString = It.IsAny<string>();
mockDependency.Setup(x => x.GetValue(anyString)).Returns("expected value");
var service = new MyService(mockDependency.Object);
var result = service.UseTheDependency("something random");
Assert.That(result, Is.EqualTo("expected value"));
}
}
Setup
方法将Linq表达式(Expression<Func<IDependency, string>>
)作为参数,而不是委托(Func<IDependency, string>
)。它允许Moq检查抽象语法树,以了解正在配置的调用。如果您使用在表达式外部声明的变量,Moq不知道您使用了It.IsAny
,它只看到了null
(从技术上讲,它看到了对封装捕获的局部变量的对象的字段anyString
的访问,而该字段只包含null
)。
编辑:我很久以前就写了这个答案,现在我意识到它有一部分是错误的。多年来,我一直是FakeIseasy(另一个嘲讽库)的维护者,它使用了类似于Moq的方法,所以现在我对它有了更好的理解…
不应该执行It.IsAny
;它被执行,并产生一个参数约束。但是,只有当Moq具有该约束的上下文时,才在Setup
中评估调用表达式时捕获该约束。如果您只是在对Setup
的调用之外调用It.IsAny
,当没有上下文时,生成的约束不会被捕获,而是被丢弃。