用于排序随机List <object>的单元测试

时间:2017-05-16 07:48:54

标签: unit-testing sorting java-7 junit4 easymock

我有一个班级,他们唯一的任务就是选择List<Object>并返回已排序的List<Object>。例如,类中的sort方法使用一个过程,该过程将对象随机放置在列表中。

尝试执行:为该排序方法(或类)编写测试,如果排序实际上只是随机的,则必须失败。这意味着我需要找到List<Object>命令来测试我假设。

要测试的代码

class RootLoggerFirstSorter {

List<LoggerConfig> sort(List<LoggerConfig> unSortedList) {

    List<LoggerConfig> levelSortedList = new ArrayList<>(unSortedList);

    Collections.sort(levelSortedList, new Comparator<LoggerConfig>() {
        @Override
        public int compare(LoggerConfig o1, LoggerConfig o2) {
            if (o1.getLevel().intLevel() == o2.getLevel().intLevel()) {
                return 0;
            } else if (o1.getLevel().intLevel() < o2.getLevel().intLevel()) {
                return 1;
        } else {
            return -1;
        }
    }}
    );

    LinkedList<LoggerConfig> sortedList = new LinkedList<LoggerConfig>();
    for(Iterator<LoggerConfig> i = levelSortedList.iterator(); i.hasNext();) {
        LoggerConfig cfg = i.next();
        addNextLoggerConfig(cfg, sortedList);
    }
    return sortedList;
}

private void addNextLoggerConfig(LoggerConfig cfg, LinkedList<LoggerConfig> sortedList) {

    if(cfg.getName() == null || cfg.getName().isEmpty()) {
        sortedList.addFirst(cfg);
    } else {
        sortedList.addLast(cfg);
    }
}
}

尝试

    .....
    expect(item1.getLevel()).andStubReturn(Level.DEBUG);
    expect(item2.getLevel()).andStubReturn(Level.ERROR);
    expect(item3.getLevel()).andStubReturn(Level.INFO);
    .....
 //Ignore the pre req for test setup 
    @Test
public void testSort() {

    List<LoggerConfig> unsortedList = makeUnsortedList();
    EasyMock.replay(item1,item2,item3);

    List<LoggerConfig> sortedList = tested.sort(unsortedList);

    assertThat("First item on the list is ERROR level: ", sortedList.get(0).getLevel(), is(Level.ERROR) );
    assertTrue(sortedList.get(1).getLevel().equals(Level.INFO) || sortedList.get(1).getLevel().equals(Level.INFO));
    assertTrue(sortedList.get(2).getLevel().equals(Level.DEBUG) || sortedList.get(2).getLevel().equals(Level.DEBUG));
}

但是这个测试总是会通过,因为如果仅查看索引1和2,索引0将始终包含具有空名称的LoggerConfig [设置以这种方式完成])。所以我想我应该单独测试比较方法吗?如果是,怎么做?

问题问题是我需要使用特定的Object属性测试sort方法,该属性是LoggerConfig对象的级别。因此,测试必须检查List顺序。

3 个答案:

答案 0 :(得分:2)

这里有许多不同的方面:

  • 当然,您无需测试内置 Collections.sort()方法。
  • 在这个意义上:相反,你要测试两个方面A)你实际上正在调用那种排序方法B)你的比较器按预期工作。

A)是通过您在自己的答案中输入的代码实现的。或者确切地说:您需要一个测试用例,您可以对其进行排序检查预期结果;在为您的方法提供特定的测试输入之后。

B)是通过编写测试代码来实现的,该代码只是检查compareTo()返回不同输入的预期结果

最后,这是关于正确将您的逻辑分解为类。当然你可以将比较器声明为匿名内部类;并只验证sort方法返回预期的结果。

但是当你制作比较器时,在某个地方说一个内部类,你可以只为比较器功能编写单元测试。

最后:您的测试用例表示您声明的目标如果排序实际上只是随机,则必须失败。你看,如果sort()的结果是 random ,它可以随机给你一个正确的结果。含义:您不能指望单个测试来验证“可能的随机行为”。您必须使用大量不同的数据运行许多测试,并验证它们的全部是否通过;实现某种置信度,sort()不是纯随机的。

但是如上所述:你没有排序。您正在调用内置排序方法,需要进行测试。

答案 1 :(得分:0)

  

我应该只对比较方法进行单元测试吗?

不,你不应该。如果您稍后尝试重构排序方法,则测试可能会失败。您实际上是在尝试断言可能已完成排序。比较方法只是一个实现细节。您可能不会使用比较方法将来对列表进行排序。

当然,您也不需要测试内置排序方法,因为您实际上是在测试自定义排序方法。此排序方法中的任何内容都是实现细节,包括您调用的list.sort方法。在编写测试时,你应假装不知道它。

除此之外,您的sort方法还包含一些与内置排序方法无关的逻辑。

答案 2 :(得分:0)

我认为List<ConfigLogger>item1["", ERROR], item2["com.fwk.foo", DEBUG], item3["com.fwk.core.baa", INFO]之类的东西有关。因此,在这种情况下,我需要检查如果item3在位置1并且item2在列表中的位置3,则实现正确排序。所以我需要的测试如下:

    @Test
    public void testSort() {
    List<LoggerConfig> unsortedList = makeUnsortedList();
    EasyMock.replay(item1,item2,item3);

    List<LoggerConfig> sortedList = tested.sort(unsortedList);

    assertFalse(unsortedList.equals(sortedList));
    assertTrue(sortedList.get(0).getName().isEmpty());

    LoggerConfig cfg1 = sortedList.get(1);
    LoggerConfig cfg2 = sortedList.get(2);

    assertThat(cfg1.getLevel(), is(Level.DEBUG));
    assertThat(cfg2.getLevel(), is(Level.INFO));
}

所以我从列表中访问该项目并比较它们是否与预期相同。