2011-07-05 154 views
2

我正在学习Mockito。在开始使用模拟对象之前,我不得不说更像集成测试一些单元测试,所以我有这样一个setUpBeforeClass(试验班):Junit/Mockito:选择运行模拟测试或集成测试

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

现在用模拟对象是相似的很多,但是设置略微复杂一些:

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

而且我有一个测试套件,用于在运行测试之前加载DB在一个众所周知的状态,这是由称为第一类测试完成该套件。

我在想,我不应该扔掉集成测试,所以我正在考虑将测试套件分成一个UnitTestSuite和一个IntegrationTestSuite。事实上,模拟测试并没有测试所有的东西,例如他们不测试查询是否正确。

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

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

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

回答

9

一定要记住,单元测试(使用mock)背后的想法是戳和单个类的所有黑暗角落。他们的目的是确保班级按照您所想的所有类型的输入行为。这就是为什么我们使用mock做这件事的原因,因为我们可以编程这些mock来做各种可能难以再现的事情,如果这个类与应用程序的其他部分联系在一起的话。

另一方面,集成有不同的重点。这是关于确保你所有的课程一起工作,以产生预期的结果。所以在编码时要记住这一点。这是你以后的大局。你不需要担心模糊单个类的边缘情况,因为这是模拟单元测试的工作。但是像数据库状态这样的事情正是为什么集成测试很重要。

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

我会建议保持您的单元测试和集成测试在单独的目录或至少单独命名匹配的软件包。简单,因为它可以帮助你记住你正在处理的事情。

还要小心测试蠕变。 IE浏览器。实例化大量应用程序类的单元测试,实际上应该被转移到集成测试中,并且集成测试正在为一个类做很多详细的变体样式测试 - 单元测试的候选。特别是对于最后一个,如果存在不应该存在的集成测试,则可以修剪大量时间。

最后,像任何代码一样,测试代码不时需要一点爱和关注。因此请留意重构机会。话虽如此,我还看到测试代码已变得难以使用,因为它太泛化且过度设计。记住测试代码不是生产代码,所以在大多数情况下,清晰度比工程更重要。这是一个平衡,你会通过经验。

+0

Upvoted为关于'测试蠕变'的段落。集成测试和单元测试通常在使用模拟方面有所不同,单元测试涵盖单一类合同,集成测试覆盖(部分)用例与整个系统。 –

+0

谢谢Derek,所以在实践中你说的是,运行与集成和单元测试相同的测试可能不是一个好主意,只是重复一种方法,因为我会错过测试的不同重点,而我或许过度设计了测试,所以我不妨将其与一些代码重复进行交换。它是否正确? – stivlo

+0

是的,差不多。我确信有些人会不同意代码重复,但如果有助于保持清晰的话,我不介意有点重复。它非常依赖于你的测试。如果你无法花费30分钟时间来阅读和理解它们,那么它们就太复杂了。另一方面,如果在包含单元测试的类中看到4次或5次相同的设置,则可能将其重构为抽象或setup()方法。正如我所说,这是一个基于代码的个人通话。最好的指南是KISS。 – drekka

0

我建议使用内存数据库进行集成测试,而不是模拟对象。

对于单元测试,我假设你使用数据库作为存根提供一些数据到测试中,并作为模拟测试时调用类似saveMyDomainObject()的东西。在第一种情况下,您只能嘲笑您对特定测试实际需要的内容,而不是整个数据库设置。对于第二种情况,您应该使用Mockito的validate来检查预期行为是否正确。

+0

实际上,我正在使用仅测试db模式进行集成测试,我在每次测试运行时重新加载(真正的db包含数百万条记录,但我在测试数据库中只有几千个,因此它不会没多久)。我正在使用,或者更好地开始使用模拟对象进行单元测试。 使用内存数据库的优势可能会更快一些,但这意味着需要额外的努力来消除SQL不兼容问题,并且这意味着我不再在真实平台上进行测试,因此它可能工作得很好在内存数据库中,并在SQL差异的实际平台上失败。 – stivlo