首页 > 解决方案 > EasyMock 的 .times(x) 方法是单元测试稳健性的问题吗?

问题描述

我目前正在使用 JUnit 和 EasyMock 为我的应用程序进行一些单元测试,以模拟复杂的对象,我正面临着两难境地。例如,我正在使用以下测试模板测试每个函数:

public static int foo(Object a){
// my function that needs to be tested

  int quantity = 0;
  if(a != null && a.getInt() != null ){
    quantity = a.getInt();
  }
  return quantity;

}

public void testFoo(){
// my unit test for the function foo
  int expectedValue = 0;
  int output = 0;

//Setting up my mocks
  Object a_mock = EasyMock.create(Object.class)
  EasyMock.expect(a_mock.getInt()).andReturn(null).times(1);
  EasyMock.expect(a_mock.getInt()).andReturn(1).times(2);

//Executing
  // Case 1: a is null
  expectedValue = 0;
  output = foo(null);
  assertEquals(expectedValue, output);

  // Case 2: a.getIn() is null
  expectedValue = 0;
  output = foo(a_mock);
  assertEquals(expectedValue, output);

  //Case 3: nominal case
  expectedValue = 1;
  output = foo(a_mock);
  assertEquals(expectedValue, output);

}

这个结构工作得很好,但我的观点是:单元测试是一个测试过程,它允许你验证每个单元(这里是一个函数)是否在知道输入的情况下给你想要的输出。这意味着如果我需要修改我的函数 foo,但不修改它的作用,我的单元测试仍然必须通过。理论上,如果 foo 像这样改变:

public static int foo(Object a){

  int quantity = 0;
  if(a != null && a.getInt() != null && a.getInt() != 5){ //modification here
    quantity = a.getInt();
  }
  return quantity;

}

然后 testFoo 仍然必须通过。 但它没有,因为.times(2)必须在.times(3).

所以这是我的问题:EasyMock 的 .times(x) 方法是单元测试稳健性的问题吗?如果不是,那么单元测试必须具备的最低稳健性水平是多少?

标签: unit-testingautomated-testseasymock

解决方案


首先,正如评论中提到的,您可能根本不需要通过模拟a。也许使用一些真实的实例Object很简单,并且不会对您的测试产生任何负面影响。

其次,如果您得出的结论是模拟是必要的,那么您可以times通过为每个测试提供单独的模拟来避免使用。您只需要调用时间,因为您a_mock在不同的测试之间重复使用。

更进一步,您甚至应该考虑将您的函数拆分testFoo为三个不同的函数 - 或直接转换testFoo为具有三个参数集的参数化测试。


推荐阅读