Nam*_* VU 7 unit-testing moq mocking
假设我们正在测试C类,它有两种方法M1和M2,其中M1在执行时调用M2.
测试M2没问题,但我们如何测试M1呢?困难在于,如果我不误解事物,我们需要模拟M2.
如果是这样,我们如何在测试同一个类中定义的方法时模拟另一个方法?
[编辑]
C类没有基类.
您可以通过将mock上的CallBase属性设置为来执行此操作true.
例如,如果我有这个类:
public class Foo
{
public virtual string MethodA()
{
return "A";
}
public virtual string MethodB()
{
return MethodA() + "B";
}
}
Run Code Online (Sandbox Code Playgroud)
我可以设置MethodA并调用MethodB:
[Fact]
public void RunTest()
{
Mock<Foo> mockFoo = new Mock<Foo>();
mockFoo.Setup(x => x.MethodA()).Returns("Mock");
mockFoo.CallBase = true;
string result = mockFoo.Object.MethodB();
Assert.Equal("MockB", result);
}
Run Code Online (Sandbox Code Playgroud)
您应该让调用M1传递给方法的实际实例M2.
通常,您应该测试类的黑盒行为.你的测试不应该关心M1调用M2- 这是一个实现细节.
这与模拟外部依赖项(您应该这样做)不同......
例如,假设我有一个这样的类:
class AccountMerger
{
public AccountMerger(IAccountDao dao)
{
this.dao = dao;
}
public void Merge(Account first, Account second, MergeStrategy strategy)
{
// merge logic goes here...
// [...]
dao.Save(first);
dao.Save(second);
}
public void Merge(Account first, Account second)
{
Merge(first, second, MergeStrategy.Default);
}
private readonly IAccountDao dao;
}
Run Code Online (Sandbox Code Playgroud)
我希望我的测试表明:
调用Merge(first, second, strategy)两个已保存的帐户的结果已使用提供的规则合并.
调用Merge(first, second)两个已保存的帐户的结果已使用默认规则合并.
请注意,这些要求都是根据输入和效果来表达的- 特别是,我并不关心课程如何实现这些结果,只要它确实如此.
第二种方法碰巧使用第一种方法的事实不是我关心的事情,甚至我想强制执行 - 如果我这样做,我会写非常脆弱的测试.(甚至有一种说法是,如果你使用模拟框架搞乱了测试中的对象,你甚至不再测试原始对象,那么你在测试什么?)这是一个内部依赖,可以很愉快改变而不违反要求:
// ...
// refactored AccountMerger methods
// these still work, and still fulfil the two requirements above
public void Merge(Account first, Account second, MergeStrategy strategy)
{
MergeAndSave(first, second, strategy ?? MergeStrategy.Default);
}
public void Merge(Account first, Account second)
{
// note this no longer calls the other Merge() method
MergeAndSave(first, second, MergeStrategy.Default);
}
private void MergeAndSave(Account first, Account second, MergeStrategy strategy)
{
// merge logic goes here...
// [...]
dao.Save(first);
dao.Save(second);
}
// ...
Run Code Online (Sandbox Code Playgroud)
只要我的测试只检查输入和效果,我就可以轻松地进行这种重构 - 我的测试甚至可以帮助我这样做,因为他们确保我在进行更改时没有打破课程.
另一方面,我做的是在合并后AccountMerger使用IAccountDao保存帐户(尽管不AccountMerger应该关心DAO的实现,只是它有一个Save()方法.)这个DAO是模拟的主要候选者 - 外部该依赖性AccountMerger类,感觉的效果我要检查一定的投入.
| 归档时间: |
|
| 查看次数: |
2021 次 |
| 最近记录: |