单元测试和集成测试示例

时间:2013-02-25 12:44:17

标签: unit-testing integration-testing database-testing

我在Test类中创建了以下四个测试,用于测试CompanyService的findCompany()方法。

@Test
public void findCompany_CompanyIdIsZero() {
    exception.expect(IllegalArgumentException.class);
    companyService.findCompany(0);
}
@Test
public void findCompany_CompanyIdIsNegative() {
    exception.expect(IllegalArgumentException.class);
    companyService.findCompany(-100);
}
@Test
public void findCompany_CompanyIdDoesntExistInDatabase() {
    Company storedCompany = companyService.findCompany(100000);
    assertNull(storedCompany1);
}

@Test
public void findCompany_CompanyIdExistsInDatabase() {
    Company company = new Company("FAL", "Falahaar");

    companyService.addCompany(company);

    Company storedCompany1 = companyService.findCompany(company.getId());
    assertNotNull(storedCompany1);
}

我的理解是前三个是单元测试。他们测试findCompany()方法的行为,检查方法将如何响应不同的输入。 第四个测试虽然放在同一个类中,但实际上似乎是对我的集成测试。它需要首先将公司添加到数据库中,以便稍后可以找到它。这引入了外部依赖项 - addCompany()和数据库。

我是对的吗?如果是,那么我应该如何单元测试查找现有对象?只是嘲笑服务“找到”一个?我认为这会破坏测试的目的。

我感谢此处的任何指导。

2 个答案:

答案 0 :(得分:1)

我这样看:你在这里测试的“单位”是CompanyService。从这个意义上讲,所有测试对我来说都是单元测试。但是,在您的服务下面,可能还有另一项服务(您提到数据库),该测试也在运行?这可能会开始模糊整合测试的线条,但你必须问自己是否重要。你可以存根任何这样的底层服务,你可能想要:

  1. 基础服务设置或使用缓慢,使您的单元测试速度太慢。
  2. 您希望确保此测试的行为不受基础服务的影响 - 即,如果CompanyService中存在错误,则此测试应该失败。
  3. 根据我的经验,如果底层服务足够快,我不会过分担心依赖它的单元测试。我不介意在我的单元测试中漏掉一些集成,因为它有好处(更多集成覆盖)并且很少导致问题。如果确实会导致问题,您可以随时返回并添加存根以改善隔离。

答案 1 :(得分:1)

[1,2,3,4]可以是基于单元的(模拟|非模拟)和基于集成的测试。这取决于你想要测试的内容。

  • 为什么要使用嘲笑?正如Jason Sankey所说... 仅测试服务层而不是层次
  • 为什么要使用嘲笑?您的业​​务逻辑可以具有多种形式。因此,您可以为一种服务方法编写多个测试,例如。创建人(没有地址 - 例外,没有银行帐户 - 例外,人没有填充非空属性 - 例外)。

您能想象每个测试请求数据库以测试所有可能的异常状态(没有地址,没有银行帐户等)吗?为了测试所有异常状态,填充数据库的工作量太大。为什么不使用模拟对象,例如。像'残缺'的对象,不包含预期的价值。每个测试构造都拥有'残缺'模拟对象。

模拟各种状态===您的测试将尽可能简单,因为每种测试方法只会测试一种状态。这些测试将清晰易懂,易于理解。如果我写一个测试,这是我想达到的目标之一。