模拟私有字段分配的最佳技巧/解决方法?

时间:2016-11-09 20:32:06

标签: tdd mockito field variable-assignment

TDD和Mockito在这里测试newb ...我最近发现了关于注入私人田地的嘲笑,并试图直截了当地提出我的想法。

很可能我对这个特定问题的看法都是错误的,但只是我经常发现我想要测试的情况,即调用特定方法导致私有字段被分配:在调用它之前是null,并且在调用之后它被设置为任何类的实例。

当您开始运行测试方法时,模拟的私有字段是该类的子类,因此显然对null的测试没有意义/不起作用。同样,如果您的方法导致分配此字段,则意味着模拟变量已被真实实例替换。因此,即使调用方法,它也不会导致与mock变量的任何交互。无论如何,如果测试只是为了检查创建和分配,那么你没有理由想要在测试中与它进行任何交互。

显然,一个答案是在app类中创建public get()方法或public create()方法。但这给我一种不好的感觉,因为它显然只是为测试目的而做。

顺便说一下,有些人,毫无疑问在TDD上比我更有经验,他会说我变得太精细了,不应该测试像田地一样具体的东西。但我对TDD最极端的方法的理解是“不用没有测试就写一行代码”。我真的想在这个阶段尽可能坚持这一点。根据经验,我可能会更加了解如何以及何时偏离这一原则。

只是我认为某个字段的赋值是一个“类事件”(主机类),与任何其他类型的事件一样值得,例如一旦实例被调用就在字段上调用方法分配到现场。我们不应该以某种方式测试它吗?在这种情况下,Mockito职业选手接受这一点可能是合法的事情吗?

后...

法比奥的评论突出了一种紧张感,作为一个新手,我感到困惑的是,“从不写一条没有测试的线”和“只测试公共方法”:这种影响不可避免地暴露出来的东西比我想,纯粹是为了测试。

他所说的“一直在改变测试”我也发现有问题:如果我们注入模拟私有字段并使用它们,那么如果我们改变“实现细节”,我们将不得不改变测试。这个想法也没有让我感到恐惧:感知变化的需要,你看看现有测试方法的解释性名称,并决定哪些不再适用,当然你创建新的......测试代码,像应用程序代码一样,必须一直在改变,对吧?

测试代码是不是像某种模具或模具一样,它引导和约束应用程序代码但同时可以脱离它?通过Mockito允许我们模拟私有字段,已经授予了一种特权形式的访问权限...谁能说这个特权访问应该在多大程度上正确扩展?

甚至更晚......

杰夫鲍曼建议这是this的副本。我并不完全相信,因为我问的是一个非常具体的事情,它可能会有一个特定的答案(一些Mockito检测任务的方法)。但他的答案似乎非常全面,我试图完全理解这一切......包括整个依赖注入事物......以及你似乎必须在“扭曲”你的公共界面以使应用程序类成为一个妥协你可以试试它。

1 个答案:

答案 0 :(得分:0)

简单示例:您需要使用两个Class1Method1方法编写一个类Method2,这两个方法返回一些Helper类提供的值。

  1. [测试]开始为第一种方法编写测试 - 它不会编译
  2. [Production]创建类Class1和Method1 - 编译确定和 测试失败
  3. [生产]在Method1中,您创建了Helper的新实例,并调用了一些返回预期值的方法 - 测试通过
  4. [测试]为同一Method1创建另一个测试用例 - 测试失败
  5. [生产]在Method1中进行更改以满足两个测试用例 - 测试为绿色
  6. [制作]如果看到可能性,请在Method1进行一些重构 - 测试必须保持绿色
  7. [测试]为Method2创建测试,该测试将更新Field1的某些公开字段Class1 - 无法编译
  8. [制作]在Method2中创建方法Field1和字段Class1 - 编译 - 确定,测试失败
  9. [制作]在Helper中创建Method2类的新实例,将其称为方法并使用预期值更新Field1 - 测试通过
  10. [测试]为Method2创建另一个测试用例 - 测试失败
  11. [生产]在Method2中进行更改以满足两个测试用例 - 测试为绿色
  12. 现在您已经实现了所需的行为,并注意到Method1Method2都创建了Helper类的实例。

    1. [生产]因此,您决定声明类型Helper的私有字段并在两种方法中使用它 - 所有测试都失败 - 因为您的私有字段未实例化。
    2. [Production] - 在构造函数中实例化新实例 - 所有测试都是绿色
    3. 稍后,如果您决定将Helper类的创建移到外部并将其作为构造函数的参数传递给Class1,则只需更改生产代码,测试将显示您是否已中断任何不改变测试的东西。

      我的回答的主要观点是,如果您认为"我想写这行代码 - 我如何测试它" - 它会让你知道你现在遇到的那种情况 尝试首先考虑您要测试的内容,并在编写测试后考虑如何实现它。