0

我想测试一下,是否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. 由于调试器永远不会到达方法中的断点,因此它似乎是自我模拟的问题getAllOrderedByName

如何使用anyJMockit 存根静态方法?

4

3 回答 3

5

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

您可能假设期望块内的任何方法调用都会被自动模拟,但这不是JMockit API 的工作方式。相反,您需要通过声明一个模拟字段或一个用、、或注释的模拟参数来明确指定哪些类型是模拟的。@Mocked@NonStrict@Cascading@Capturing

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

此外,无论如何我都不推荐这样编写测试。相反,它应该验证结果集合是否已排序,而无需模拟Collections类。

于 2013-06-07T11:55:56.937 回答
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());
于 2013-06-06T15:43:39.380 回答
1

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

首先,测试您的Comparableon 是否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)。

于 2013-06-06T15:52:43.197 回答