为什么关于'部分嘲笑'以及需要它的代码会如此讨厌呢?
这是一个(理论上的)示例实现:
public ComplexResult1 operationA(Stimulus a) {
{
...
result = ...;
}
auditTheChange(a);
}
public ComplexResult2 operationB(Stimulus b) {
{
...
result = ...;
}
auditTheChange(b);
return result;
}
void auditTheChange(Stimulus stim) {
// do a bunch of stuff to record the change
// and interact with another outside service
}
现在,根据我的理解,这是重构良好的代码。
如果我想UNIT测试operationA和operationB,和确保在每个场景中都进行审计,但是没有必须测试审计代码的细节,我会使用部分嘲弄。
我没有看到/理解导致如此多的项目(EasyMock,Mockito等)推荐重构?
答案 0 :(得分:4)
如果审计确实是该类的内部功能,那么代码应作为单元测试的一部分进行测试。为什么你的类处理复杂的操作和审计?审计是否可以移到另一个班级?
如果是这样,请将审计作为此类的协作者介绍并嘲笑它。如果没有,请进行单元测试。
你可以使用部分嘲笑,但在这种情况下,我认为这表明课程做得太多了。
答案 1 :(得分:1)
如果auditTheChange
是一个私有函数,那么您只需不编写验证其调用的测试。
您不希望单元测试与实现紧密结合。
一般来说:不要对私有方法进行单元测试。
答案 2 :(得分:0)
关键点是“正在测试的单元是什么”。
许多开发人员都认为OO。在OO中,“对象”是软件的单元,因此对象也是在单元测试中测试的单元。在您的示例中,auditTheChange()是对象中的私有方法。单元测试应仅关注公共方法的行为。模拟私有方法意味着单元测试用例处理单元的一些实现细节,这被认为是“代码异味”。
一些开发人员认为软件的单位是“方法”。在您的示例中,您确实以这种方式思考。由于operationA和operationB过于紧凑,因此您可以创建auditTheChange,从而可以降低单元operationA和operationB的复杂性。如果您以这种方式考虑,则部分模拟不是“代码异味”,因为该方法是要测试的单元,而模拟私有方法也意味着“关注行为而不是实现细节”。
这里没有过时的正确或错误。这实际上取决于您的项目或团队的性质。我为公司工作,使用Spring开发企业信息系统。在Spring中,几乎所有业务逻辑都在xxxService对象中实现。当方法太复杂时,我们只是像您在示例中所做的那样,将一些逻辑移至私有方法。如果我们总是将这些逻辑移到新的类上,将会创建许多类和对象,并使程序更难以维护。因此,我们只是将逻辑移至私有方法并使用部分模拟。实际上,很多人都需要部分模拟。您可以检查此Mockito文档。最初,mockito认为部分模拟是代码异味。经过长时间的讨论和辩论,他们现在也支持部分模拟。