Mockito - Objekte miteinander vergleichen (equals)

jCoder1984

Aktives Mitglied
Hallo
Ich habe einen MemberController geschrieben, der Member Objekte hinzufügen und löschen kann

Hier der Code :
Java:
...
    @NonNull
    @Setter(AccessLevel.NONE)
    protected final List<Member> memberList = Lists.newArrayList();

    /**
     * try to add a new {@link Member} to the list <br>
     * if the member exists already in the list return it <br>
     * otherwise return the new member <br>
     *
     * @return the existsing or the new created member <br>
     */
    public Member addMember(@NonNull Member member) {
    Optional<Member> optional = memberList.stream().filter(e -> e.equals(member)).findFirst();
    Member tmpMember = null;

    if (optional.isPresent()) {
        log.debug("the member [{}] exists already in the memberList", member);
        tmpMember = (Member) optional.get();
    } else {
        log.info("add the member [{}] into the memberList", member);
        tmpMember = member;
        memberList.add(member);
    }

    return tmpMember;
    }

    /**
     * remove a {@link Member} of the list <br>
     */
    public void removeMember(@NonNull Member member) {
    Optional<Member> optional = memberList.stream().filter(e -> e.equals(member)).findFirst();

    if (optional.isPresent()) {
        log.info("remove the member [{}] from the memberList", member);
        memberList.remove(member);
    }
    }

Nun würde ich das Hinzufügen und Löschen gerne in einem Unit Test testen. Mein Problem : Das Member Objekt ist nur als Interface bekannt. Die konkrete Implementierung erfolgt in einem anderen Projekt. Daher verwende ich Mockito.

Hier ein Test

Java:
    @Test
    public void testAddRemoveMember() {
    MemberController controller = new MemberController();
   
    // create the first member mock
    Member member1 = Mockito.mock(Member.class);
    Mockito.when(member1.getLastName()).thenReturn("lastName");
   
    // create the second member mock
    Member member2 = Mockito.mock(Member.class);
    Mockito.when(member2.getLastName()).thenReturn("lastName");
    Mockito.when(member2.equals(member1)).thenReturn(true);
   
    // create the third member mock
    Member member3 = Mockito.mock(Member.class);
    Mockito.when(member3.getLastName()).thenReturn("otherLastName");

    // add the first member
    controller.addMember(member1);
    Assert.assertNotNull("memberList may not be null", controller.getMemberList());
    Assert.assertEquals("memberList content", Lists.newArrayList(member1), controller.getMemberList());
   
    // add the second member
    controller.addMember(member2);
    Assert.assertNotNull("memberList may not be null", controller.getMemberList());
    Assert.assertEquals("memberList content", Lists.newArrayList(member1), controller.getMemberList());
    }

Ich möchte hier testen, wie sich die Liste verhält wenn ich 2x mal das gleiche Member Objket hinzufügt. Daher haben member1 und member2 auch den gleichen Nachnamen.
Ich habe versucht das über die equals methode zu realisieren.

Allerdings bekomme ich bei der Testausführung einen Fehler
Java:
org.mockito.exceptions.misusing.MissingMethodInvocationException:
when() requires an argument which has to be 'a method call on a mock'.
For example:
    when(mock.getArticles()).thenReturn(articles);

Also, this error might show up because:
1. you stub either of: final/private/equals()/hashCode() methods.
   Those methods *cannot* be stubbed/verified.
2. inside when() you don't call method on mock but on some other object.
3. the parent of the mocked class is not public.
   It is a limitation of the mock engine.

Kann mir jemand weiterhelfen.

Vielen Dank
 
Indem man solche Fälle am besten vermeidet 😀

Du kannst die nötigen Objekte einfach per Hand als anonyme Klasse erstellen, damit kannst du zumindest die Mockito-Beschränkung umgehen
 
Wenn du deinen Member nur anhand des lastname Vergleichst, dann könntest du doch die beiden Felder als String rausschreiben und den String vergleichen. Oder habe ich da einen Denkfehler?
 
Wenn du deinen Member nur anhand des lastname Vergleichst, dann könntest du doch die beiden Felder als String rausschreiben und den String vergleichen. Oder habe ich da einen Denkfehler?

Die Implementation der Member-Klasse kann equals überschreiben, wie sie lustig ist, das muss nicht auf lastname beruhen.
 
Zuletzt bearbeitet:

Zurück
Oben