问题
I need to test the compare() method and i am confused on how. Can I see how to do this?
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());
}
}
}
So far, this is what i have created in my test. How can i get this to work? What should i do as this way isn't working, assuming i do not change the current approach to MemberComparator class.
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);
}
}
回答1:
Some assertions might look like:
assertTrue(comparator.compare(m1, m1) == 0);
assertTrue(comparator.compare(m1, m2) > 0);
assertTrue(comparator.compare(m2, m1) < 0);
回答2:
There are two questions you'd need to answer when writing a Comparator
:
- Does it meet the requirements of the
Comparator
interface? - Does it do what you need?
The first one is reasonably hard to write tests for; I'd argue it's better to write something using a "known good" pattern, in order to help you reason about its correctness from the code.
In the case of Comparator
, the "known good" pattern is something that you see from the chaining methods:
// 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)
You compare the first thing, and return if they're different; you compare the second thing, and return if they're different, etc.
You could use the code above if you're using Java 8+: this gives a totally fine Comparator
. If you can't use this (for whatever reason), your compare
method could be rewritten as:
int compareSw = Boolean.compare(m1.getClientId().startsWith(clientId), m2.getClientId().startsWith(clientId));
if (compareSw != 0) {
return compareSw;
}
return m1.getClientId().compareTo(m2.getClientId());
Because this follows the "known good" pattern, this can be seen to meet the requirements of the Comparator
interface by inspection.
(Of course, you have to be careful about thinking "Looks Good To Me!", because you might miss something, e.g. using m1.getClientId()
twice instead of both m1.getClientId()
and m2.getClientId()
. But that sort of defect would be caught by sufficient testing of the following).
Then it's just a matter of testing to make sure it does what you want: that is, if you take two Member
s, does this Comparator
order them the way you want? That's an easy test to write, without getting bogged down in the details of the Comparator
.
List<Member> members = List.of(m1, m2);
assertEquals(m1, Collections.min(members, comparator)); // For example.
assertEquals(m2, Collections.max(members, comparator)); // For example.
来源:https://stackoverflow.com/questions/65923065/how-to-test-comparator-for-junit-test