关于单元测试:烘干EasyMock测试

DRYing Up EasyMock Tests

EasyMock测试似乎倾向于遵循以下模式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Test
public void testCreateHamburger()
{
  // set up the expectation
  EasyMock.expect(mockFoodFactory.createHamburger("Beef","Swiss","Tomato","Green Peppers","Ketchup"))
    .andReturn(mockHamburger);

  // replay the mock
  EasyMock.replay(mockFoodFactory);

  // perform the test
  mockAverager.average(chef.cookFood("Hamburger"));

  // verify the result
  EasyMock.verify(mockFoodFactory);
}

这对于一个测试工作正常,但是当我想用另一种方法再次测试相同的逻辑时会发生什么呢?我首先想到的是做这样的事情:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Before
public void setUp()
{
  // set up the expectation
  EasyMock.expect(mockFoodFactory.createHamburger("Beef","Swiss","Tomato","Green Peppers","Ketchup"))
    .andReturn(mockHamburger);

  // replay the mock
  EasyMock.replay(mockCalculator);
}

@After
public void tearDown()
{
  // verify the result
  EasyMock.verify(mockCalculator);
}

@Test
public void testCreateHamburger()
{
  // perform the test
  mockAverager.average(chef.cookFood("Hamburger"));
}

@Test
public void testCreateMeal()
{
  // perform the test
  mockAverager.average(chef.cookMeal("Hamburger"));
}

这种方法存在一些基本问题。首先是我的方法调用不能有任何变化。如果我想测试person.cookFood("Turkey Burger"),我的设置方法将不起作用。第二个问题是我的设置方法要求调用createHamburger。如果我呼叫person.cookFood("Salad"),那么这可能不适用。我可以在EasyMock中使用anyTimes()stubReturn()来避免此问题。但是,这些方法仅验证是否已调用某个方法(是否已调用某些参数),而不验证是否已实际调用该方法。

到目前为止,唯一有效的解决方案是复制并粘贴每个测试的期望值并更改参数。有谁知道使用EasyMock保持DRY原理的更好的测试方法吗?


您遇到的问题是因为单元测试应该是DAMP而不是DRY。单元测试将倾向于重复自己。如果您可以安全的方式删除重复(这样就不会产生不必要的耦合测试),那么就去做吧。如果不是,请不要强行使用。单元测试应该快速而简单...如果不是,那么您将花费大量时间进行测试,而不是写下业务价值。

我只有两美分。顺便说一句,Roy Osherove撰写的"单元测试的艺术"是有关单元测试的一本好书,它涵盖了这个主题。