C# 和 Moq:如何验证实例方法是否调用了正确的辅助实例方法?
C# and Moq: How to validate an instance method is calling the proper secondary instance method?
我在使用 Ruby 等其他语言进行模拟方面有很多经验,但我是 C# 中的 Moq 新手,我正在尝试验证对我来说最基本的模拟:验证一个方法正在使用正确的参数调用正确的方法。
我有这个例子主题class
public class Subject
{
int _age;
public Subject(int age)
{
_age = age;
}
public void MainMethod()
{
if(_age <= 13)
{
KidMethod();
}
else
{
AdultMethod();
}
}
public void KidMethod() {}
public void AdultMethod() {}
}
我正在尝试创建这个测试:
[Test]
public void MainMethod_ShouldCallKidMethod_IfAgeBelow1()
{
var subjectMock = new Mock<Subject>(12);
subjectMock.Verify(subject => subject.KidMethod());
subjectMock.MainMethod();
}
但显然我做错了什么,因为我得到了这个错误:
error CS1061: 'Mock' does not contain a definition for 'MainMethod' and no accessible extension method 'MainMethod' accepting a first argument of type 'Mock' could be found (are you missing a using directive or an assembly reference?)
我想我缺少对使用 Moq 模拟的一些基本理解解决这个例子将帮助我得到它。
我一直在检查 SO 中的类似问题,但我检查过的所有问题都涵盖了更具体的案例,我没有找到任何人解决这个一般的简单案例。
更新 1
正在编译:
[Test]
public void MainMethod_ShouldCallKidMethod_IfAgeBelow1()
{
var subjectMock = new Mock<Subject>(12);
subjectMock.Object.MainMethod();
subjectMock.Verify(subject => subject.KidMethod());
}
但现在我有错误:
System.NotSupportedException : Unsupported expression: subject => subject.KidMethod()
Non-overridable members (here: Subject.KidMethod) may not be used in setup / verification expressions.
看起来 Moq 不能与不能被覆盖的方法一起使用 1
有没有办法做我正在尝试的事情?
你的例子对我来说没有多大意义:你正试图模拟你正在测试的 class 的某些方法。下面是一个比较典型的例子。
您的 class 可能使用了一些接口:
public class Subject
{
private readonly IHelper _helper;
int _age;
public Subject(IHelper helper, int age)
{
_helper = helper;
_age = age;
}
public void MainMethod()
{
if(_age <= 13)
{
_helper.KidMethod();
}
else
{
_helper.AdultMethod();
}
}
}
因此您的测试将模拟该界面。这样我们就可以单独测试 Subject
。
[Test]
public void MainMethod_ShouldCallKidMethod_IfAgeBelow1()
{
// Arrange.
var helperMock = new Mock<IHelper>();
var subject = new Subject(helperMock.Object, 12);
// Act.
subject.MainMethod();
// Assert.
helperMock.Verify(h => h.KidMethod());
}
重点是你要求的不是你应该做的。是的,mocking 框架可以验证方法调用,on mocks。你模拟依赖关系。
您没有依赖项,您想测试您要测试的 class 上的一个方法调用您要测试的 class 上的另一个方法。
这不是模拟或单元测试的目的,你在这里做错了。在同一个 class 上调用另一个方法的方法是一个实现细节,而不是您应该测试的东西。重要的是方法的输出,或者方法调用后对象的状态。测试 那个.
参见示例 How to use Moq in unit test that calls another method in same class。
我在使用 Ruby 等其他语言进行模拟方面有很多经验,但我是 C# 中的 Moq 新手,我正在尝试验证对我来说最基本的模拟:验证一个方法正在使用正确的参数调用正确的方法。
我有这个例子主题class
public class Subject
{
int _age;
public Subject(int age)
{
_age = age;
}
public void MainMethod()
{
if(_age <= 13)
{
KidMethod();
}
else
{
AdultMethod();
}
}
public void KidMethod() {}
public void AdultMethod() {}
}
我正在尝试创建这个测试:
[Test]
public void MainMethod_ShouldCallKidMethod_IfAgeBelow1()
{
var subjectMock = new Mock<Subject>(12);
subjectMock.Verify(subject => subject.KidMethod());
subjectMock.MainMethod();
}
但显然我做错了什么,因为我得到了这个错误:
error CS1061: 'Mock' does not contain a definition for 'MainMethod' and no accessible extension method 'MainMethod' accepting a first argument of type 'Mock' could be found (are you missing a using directive or an assembly reference?)
我想我缺少对使用 Moq 模拟的一些基本理解解决这个例子将帮助我得到它。
我一直在检查 SO 中的类似问题,但我检查过的所有问题都涵盖了更具体的案例,我没有找到任何人解决这个一般的简单案例。
更新 1
正在编译:
[Test]
public void MainMethod_ShouldCallKidMethod_IfAgeBelow1()
{
var subjectMock = new Mock<Subject>(12);
subjectMock.Object.MainMethod();
subjectMock.Verify(subject => subject.KidMethod());
}
但现在我有错误:
System.NotSupportedException : Unsupported expression: subject => subject.KidMethod() Non-overridable members (here: Subject.KidMethod) may not be used in setup / verification expressions.
看起来 Moq 不能与不能被覆盖的方法一起使用 1
有没有办法做我正在尝试的事情?
你的例子对我来说没有多大意义:你正试图模拟你正在测试的 class 的某些方法。下面是一个比较典型的例子。
您的 class 可能使用了一些接口:
public class Subject
{
private readonly IHelper _helper;
int _age;
public Subject(IHelper helper, int age)
{
_helper = helper;
_age = age;
}
public void MainMethod()
{
if(_age <= 13)
{
_helper.KidMethod();
}
else
{
_helper.AdultMethod();
}
}
}
因此您的测试将模拟该界面。这样我们就可以单独测试 Subject
。
[Test]
public void MainMethod_ShouldCallKidMethod_IfAgeBelow1()
{
// Arrange.
var helperMock = new Mock<IHelper>();
var subject = new Subject(helperMock.Object, 12);
// Act.
subject.MainMethod();
// Assert.
helperMock.Verify(h => h.KidMethod());
}
重点是你要求的不是你应该做的。是的,mocking 框架可以验证方法调用,on mocks。你模拟依赖关系。
您没有依赖项,您想测试您要测试的 class 上的一个方法调用您要测试的 class 上的另一个方法。
这不是模拟或单元测试的目的,你在这里做错了。在同一个 class 上调用另一个方法的方法是一个实现细节,而不是您应该测试的东西。重要的是方法的输出,或者方法调用后对象的状态。测试 那个.
参见示例 How to use Moq in unit test that calls another method in same class。