TDD和Mockito在这里测试newb ...我最近发现了关于注入私人田地的嘲笑,并试图直截了当地提出我的想法。
很可能我对这个特定问题的看法都是错误的,但只是我经常发现我想要测试的情况,即调用特定方法导致私有字段被分配:在调用它之前是null
,并且在调用之后它被设置为任何类的实例。
当您开始运行测试方法时,模拟的私有字段是该类的子类,因此显然对null
的测试没有意义/不起作用。同样,如果您的方法导致分配此字段,则意味着模拟变量已被真实实例替换。因此,即使调用方法,它也不会导致与mock变量的任何交互。无论如何,如果测试只是为了检查创建和分配,那么你没有理由想要在测试中与它进行任何交互。
显然,一个答案是在app类中创建public
get()
方法或public
create()
方法。但这给我一种不好的感觉,因为它显然只是为测试目的而做。
顺便说一下,有些人,毫无疑问在TDD上比我更有经验,他会说我变得太精细了,不应该测试像田地一样具体的东西。但我对TDD最极端的方法的理解是“不用没有测试就写一行代码”。我真的想在这个阶段尽可能坚持这一点。根据经验,我可能会更加了解如何以及何时偏离这一原则。
只是我认为某个字段的赋值是一个“类事件”(主机类),与任何其他类型的事件一样值得,例如一旦实例被调用就在字段上调用方法分配到现场。我们不应该以某种方式测试它吗?在这种情况下,Mockito职业选手接受这一点可能是合法的事情吗?
后...
法比奥的评论突出了一种紧张感,作为一个新手,我感到困惑的是,“从不写一条没有测试的线”和“只测试公共方法”:这种影响不可避免地暴露出来的东西比我想,纯粹是为了测试。
他所说的“一直在改变测试”我也发现有问题:如果我们注入模拟私有字段并使用它们,那么如果我们改变“实现细节”,我们将不得不改变测试。这个想法也没有让我感到恐惧:感知变化的需要,你看看现有测试方法的解释性名称,并决定哪些不再适用,当然你创建新的......测试代码,像应用程序代码一样,必须一直在改变,对吧?
测试代码是不是像某种模具或模具一样,它引导和约束应用程序代码但同时可以脱离它?通过Mockito允许我们模拟私有字段,已经授予了一种特权形式的访问权限...谁能说这个特权访问应该在多大程度上正确扩展?
甚至更晚......
杰夫鲍曼建议这是this的副本。我并不完全相信,因为我问的是一个非常具体的事情,它可能会有一个特定的答案(一些Mockito检测任务的方法)。但他的答案似乎非常全面,我试图完全理解这一切......包括整个依赖注入事物......以及你似乎必须在“扭曲”你的公共界面以使应用程序类成为一个妥协你可以试试它。
答案 0 :(得分:0)
简单示例:您需要使用两个Class1
和Method1
方法编写一个类Method2
,这两个方法返回一些Helper
类提供的值。
Class1
和Method1 - 编译确定和
测试失败Helper
的新实例,并调用了一些返回预期值的方法 - 测试通过Method1
创建另一个测试用例 - 测试失败Method1
中进行更改以满足两个测试用例 - 测试为绿色Method1
进行一些重构 - 测试必须保持绿色Method2
创建测试,该测试将更新Field1
的某些公开字段Class1
- 无法编译Method2
中创建方法Field1
和字段Class1
- 编译 - 确定,测试失败Helper
中创建Method2
类的新实例,将其称为方法并使用预期值更新Field1
- 测试通过Method2
创建另一个测试用例 - 测试失败Method2
中进行更改以满足两个测试用例 - 测试为绿色现在您已经实现了所需的行为,并注意到Method1
和Method2
都创建了Helper
类的实例。
Helper
的私有字段并在两种方法中使用它 - 所有测试都失败 - 因为您的私有字段未实例化。稍后,如果您决定将Helper
类的创建移到外部并将其作为构造函数的参数传递给Class1
,则只需更改生产代码,测试将显示您是否已中断任何不改变测试的东西。
我的回答的主要观点是,如果您认为"我想写这行代码 - 我如何测试它" - 它会让你知道你现在遇到的那种情况 尝试首先考虑您要测试的内容,并在编写测试后考虑如何实现它。