2013-02-25 115 views
1

我在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()和数据库。

我正确吗?如果是,那么我应该如何进行单元测试以查找现有对象?只是嘲笑服务“找”一个?我认为这会杀死测试的意图。

我很欣赏这里的任何指导。

回答

1

我这样看:你在这里测试的“单位”是CompanyService。从这个意义上说,你所有的测试看起来都像是单元测试。然而,在你的服务之下,可能有另一项服务(你提到一个数据库),这个测试也在进行中?这可能会开始模糊集成测试的一些线条,但是您必须问自己是否重要。您可能存根任何这样的底层服务,你可能想,如果:

  1. 基础服务是缓慢的设置或使用,使您的单元测试太慢。
  2. 您希望确保此测试的行为不受底层服务的影响 - 即只有在CompanyService中存在错误时,此测试才会失败。

根据我的经验,如果底层服务足够快,我不必过多担心依赖它的单元测试。我不介意在我的单元测试中出现一些集成漏洞,因为它具有益处(更多的集成覆盖率)并且很少导致问题。如果确实会造成问题,您可以随时回来并添加残片以改善隔离效果。

+0

嘛。底层服务(数据库调用)仅仅是Hibernate单线调用,肯定不会包含任何错误。所以,我猜我在做什么是没问题的。 – 2013-02-28 06:55:01

1

[1,2,3,4]可能是基于单位(嘲弄|不嘲弄)和基于集成的测试。这取决于你想测试什么。

  • 为什么要使用嘲讽?由于Jason Sankey说... 只测试服务层不下层
  • 为什么要使用嘲讽?您的业​​务逻辑可以有有多种形式。所以你可以写几个测试一个服务方法,例如。创建人员(没有地址 - 例外,没有银行账户 - 例外,人员没有填写非空属性 - 例外)。

你能想象,为了测试所有可能性异常状态(没有地址,没有银行账户等),每个测试请求的数据库?为了测试所有异常状态,填充数据库的工作量过大。为什么不使用模拟对象,例如。就像不包含期望值的“残缺”对象一样。每个测试构造都拥有'残缺'模拟对象。

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