【问题标题】:How to test Comparator for JUnit test?如何测试 JUnit 测试的比较器?
【发布时间】:2021-01-27 16:15:54
【问题描述】:

我需要测试 compare() 方法,但我对如何测试感到困惑。我可以看看怎么做吗?

public class MemberComparator implements Comparator<Member> {

    private final String clientId;

    public MemberComparator(String clientId) {
        this.clientId = clientId;
    }

    @Override
    public int compare(Member m1, Member m2) {
        if (m1.getClientId().startsWith(clientId)) {
            return m2.getClientId().startsWith(clientId) ? m1.getClientId().compareTo(m2.getClientId())
                    : -1;
        } else {
            return m2.getClientId().startsWith(clientId) ? 1
                    : m1.getClientId().compareTo(m2.getClientId());
        }
    }

}

到目前为止,这是我在测试中创建的。我怎样才能让它工作?假设我没有更改 MemberComparator 类的当前方法,我应该怎么做这种方式不起作用。

class MemberComparatorTest {

//private MemberComparator caseID_test;
//private final MemberComparator memberComparator = new MemberComparator("jake");

@Test
void testEqual() {
    Member m1 = new Member();
    Member m2 = new Member();
    int result = memberComparator.compare(m1,m2);
    //assertTrue("expected to be equal", result == 0);

}

}

【问题讨论】:

    标签: java unit-testing testing junit comparator


    【解决方案1】:

    在写Comparator 时,您需要回答两个问题:

    1. 是否满足Comparator接口的要求?
    2. 它能满足您的需要吗?

    第一个很难编写测试;我认为最好使用“已知良好”模式编写一些东西,以帮助您从代码中推断其正确性。

    对于Comparator,“已知良好”模式是您从链接方法中看到的:

    // This boolean comparison may be the wrong way round, I never remember which way is which. If so, reverse it.
    Comparator.comparing(m -> m.getClientId().startsWith(clientId))
        .thenComparing(Member::getClientId)
    

    你比较第一件事,如果它们不同则返回;您比较第二件事,如果它们不同则返回,等等。

    如果您使用的是 Java 8+,则可以使用上面的代码:这给出了一个非常好的Comparator。如果您不能使用它(无论出于何种原因),您的 compare 方法可以重写为:

    int compareSw = Boolean.compare(m1.getClientId().startsWith(clientId), m2.getClientId().startsWith(clientId));
    if (compareSw != 0) {
      return compareSw;
    }
    return m1.getClientId().compareTo(m2.getClientId());
    

    因为这遵循“已知良好”的模式,所以通过检查可以看出满足Comparator接口的要求。

    (当然,你必须小心思考“看起来不错!”,因为你可能会错过一些东西,例如使用m1.getClientId() 两次而不是同时使用m1.getClientId()m2.getClientId()。但是那种缺陷将通过对以下内容的充分测试来捕获)。

    那么这只是一个测试的问题,以确保它做你想要的:也就是说,如果你拿两个Members,这Comparator会按照你想要的方式排序吗?这是一个易于编写的测试,不会陷入Comparator 的细节中。

    List<Member> members = List.of(m1, m2);
    assertEquals(m1, Collections.min(members, comparator));  // For example.
    assertEquals(m2, Collections.max(members, comparator));  // For example.
    

    【讨论】:

    • 如果我不改变 MemberComparator 类呢?从那时起我将如何进行测试?
    【解决方案2】:

    一些断言可能看起来像:

    assertTrue(comparator.compare(m1, m1) == 0);
    assertTrue(comparator.compare(m1, m2) > 0);
    assertTrue(comparator.compare(m2, m1) < 0);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-01
      • 2016-05-15
      相关资源
      最近更新 更多