使用'any'使用JMockit对静态方法进行存根

时间:2013-06-06 15:40:47

标签: java collections mocking static-methods jmockit

我想测试一下,Collection.sort(...)是否被JMockit调用:

final List<Employee> employees = new ArrayList<>();
new Expectations() {
  {
    Collections.sort((List<Employee>) any);
    result = employees;
  }
};

assertThat(EmployeeRepository.getAllOrderedByName()).isSameAs(employees);

这是我在测试中的示例存储库的实现:

public class EmployeeRepository {

  private static List<Employee> employees = new ArrayList<>();

  public static List<Employee> getAllOrderedByName() {
    Collections.sort(employees);
    return employees;
  }
}

当我运行单元测试时,我在Collections.sort得到一个NullPointerException。由于调试器永远不会在getAllOrderedByName方法中达到断点,因此在自我模拟中似乎是一个问题。

如何使用JMockit使用any存根静态方法?

3 个答案:

答案 0 :(得分:5)

在测试代码中,永远不会指定Collections类进行模拟。因此,Collections.sort((List<Employee>) any);调用会抛出NPE,因为any的值为null并且执行了实际的sort方法。

您可能认为期望块内的任何方法调用都会被自动模拟,但 JMockit API的工作方式。相反,您需要通过声明使用@Mocked@NonStrict@Cascading或{注释的模拟字段或模拟参数来明确指定模拟的类型。 {1}}。

此外,在这种情况下,@Capturing是一个返回Collections.sort的方法,因此记录返回值没有意义。

此外,像这样编写测试并不是我推荐的。它应该验证生成的集合是否已排序,而不是模拟void类。

答案 1 :(得分:1)

这不能回答你的具体问题(过去我自己遇到了any的困难,所以我尽量避免它!),但你可以使用MockUp代替:

final AtomicBoolean wasCalled = new AtomicBoolean();

new MockUp<Collections> () {
    @Mock
    public <T extends Comparable<? super T>> void sort(List<T> list) {
        wasCalled.set(true);
        //no-op otherwise
    }
};

assertThat(EmployeeRepository.getAllOrderedByName()).isSameAs(employees);
assertTrue(wasCalled.get());

答案 2 :(得分:1)

如果我是你,我不会这样做。

首先,测试Comparable上的Employee是否有效。

然后创建Employee类的模拟。注意:在这里使用mockito,但我想这可以适应jmockit(我从未使用过):

private static final int NR_MOCKS = 20;

// ....

List<Employee> sorted = new ArrayList<>(NR_MOCKS);
for (int i = 0; i < NR_MOCKS; i++)
    sorted.add(mock(Employee.class));

// Create a shuffled list of the sorted list
List<Employee> shuffled = new ArrayList<>(sorted);
Collections.shuffe(shuffled);

// Inject shuffled into repository

// Stubs
for (int i1 = 0; i1 < NR_MOCKS; i1++)
    for (int i2 = 0; i2 < NR_MOCKS; i2++)
        when(sorted.get(i1).compareTo(sorted.get(i2))).thenReturn(i2 - i1);

List<Employee> actual = EmployeeRepository.getAllOrderedByName();

assertEquals(actual, sorted);

它不仅检查列表是否最终排序(因为您事先已经测试了Comparable实现),但不关心使用了哪种排序算法;它只是工作(tm)。