Junit/Mockito:选择使用模拟或集成测试进行测试

sti*_*vlo 2 java junit mockito

我正在学习Mockito.在开始使用模拟对象之前,我有一些更像集成测试的单元测试,所以我有一个带有setUpBeforeClass()的测试类,如下所示:

@BeforeClass
public static void setUpBeforeClass() throws Exception {
    instance = new UserDataAccess();
    instance.setDb(new MyDb());
}
Run Code Online (Sandbox Code Playgroud)

现在使用模拟对象很相似,但设置稍微复杂一些:

@BeforeClass
public static void setupBeforeClass throws Exception {
    instance = new UserDataAccess();
    MyDb myDb = mock(MyDb.class);
    when(...).thenReturn(...);
    ...
    instance.setDb(myDb);
}
Run Code Online (Sandbox Code Playgroud)

此外,我还有一个测试套件,用于在运行测试之前将DB加载到一个众所周知的状态,这是通过套件调用的第一个测试类来完成的.

我在想的是我不应该抛弃集成测试,因此我正在考虑将测试套件拆分为UnitTestSuite和IntegrationTestSuite.事实上,模拟测试并没有测试所有内容,例如他们不测试查询是否正确.

此外,这两个套件之间的唯一区别是初始DB重置和setUpBeforeClass()代码.复制和更改所有测试类只是为了更改方法,这将是一种浪费.初始DB重置很容易跳过,我只是不在单元测试套件中包含db reset测试类.

拆分单元和集成测试你有什么建议?扩展所有原始类以覆盖静态方法,然后在套件中包含正确的类?

还是其他方法?你是怎么做的,或者你会做什么?

dre*_*kka 9

永远记住,单元测试(使用模拟)背后的想法是戳一个类的所有黑暗角落.它们是关于确保该类的行为与您能想到的所有类型的输入一样.这就是为什么我们使用模拟来做这个,因为我们可以编程那些模拟做各种可能难以重现的事情,如果类被连接到应用程序的其余部分.

另一方面,整合有不同的侧重点.这是为了确保所有类一起工作以产生所需的结果.因此在编码时请记住这一点.这是你追求的全局.您不必担心单个类的边缘情况,因为这是您的模拟单元测试的工作.但像数据库状态这样的东西正是集成测试很重要的原因.

我也同意@stivlo关于在内存数据库工作中使用HSQL等产品.它们既可以加速集成测试,又可以帮助确保测试的已知起点.

我建议将单元测试和集成测试保存在单独的目录中,或者至少将单独的包命名为匹配.很简单,因为它可以帮助您记住您正在处理的内容.

还要注意测试蠕变.IE浏览器.实例化大量应用程序类的单元测试,实际上应该转移到集成测试,以及在类上进行大量详细变化样式测试的集成测试 - 单元测试的候选者.特别是在最后,如果存在不存在的集成测试,您可以从构建中删除大量时间.

最后,就像任何代码一样,测试代码需要不时的爱和关注.所以请留意重构机会.话虽如此,我也看到了测试代码已经变得难以使用,因为它过于笼统和过度设计.请记住,测试代码不是生产代码,因此在大多数情况下,清晰度远比工程更重要.这是您将通过经验获得的平衡.