简体   繁体   中英

JUnit4 (assertEquals) saying objects are different, when they're the same?

I'm testing my code using JUnit4 to see if an insertion sort of an array of objects ( Word(String a, int b) ) is correctly sorting the array. The problem I'm having is that when I run JUnit it fails, giving me an error: "expected {One, 1} but was {One, 1}." If I print out both values I'm comparing before I run the test they are also the same. The code is:

package sort;

import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class InsertionTest {
    private Word word1;
    private Word word2;
    private Word word3;
    private Word word4;
    private Word wordExpected1;
    private Word wordExpected2;
    private Word wordExpected3;
    private Word wordExpected4; 

    @Before
    public void setUp() throws Exception {
        word1 = new Word("One", 1);
        word2 = new Word("Two", 2);
        word3 = new Word("Three", 3);
        word4 = new Word("Four", 4);
        wordExpected1 = new Word("One", 1);
        wordExpected2 = new Word("Two", 2);
        wordExpected3 = new Word("Three", 3);
        wordExpected4 = new Word("Four", 4);
    }

    @After
    public void tearDown() throws Exception {
    }

    @SuppressWarnings("deprecation")
    @Test
    public void test() {
        Word[] wordList = { word3, word2, word4, word1 };
        Word[] expected = { wordExpected1, wordExpected2, wordExpected3, wordExpected4 };
        Insertion.sortInsert(wordList);
        assertEquals(expected, wordList);
    }
}

The code for the insertionsort:

package sort;
public class Insertion {
/**
 * regular insertion sort
 * @param x - the input array containing scores of words that need to be sorted.
 */
    public static void sortInsert ( Word[] x) {
        int N = x.length;

        for (int i = 1; i < N; i++){
            int tempScore = x[i].getScore();
            String tempWord = x[i].getWord();
            int j;

            for (j = (i - 1); j >= 0 && tempScore < x[j].getScore(); j--){
                x[j + 1].setScore(x[j].getScore());
                x[j + 1].setWord(x[j].getWord());
            }

            x[j + 1].setScore(tempScore);
            x[j + 1].setWord(tempWord);
        }
    }
}

The code for the ADT:

package sort; 
public class Word implements Comparable<Word>{
    private String word;
    private int score;

    public Word(String w, int s){
        this.word = w;
        this.score = s;
    }

    public int getScore(){
        return score;
    }

    public void setScore(int s){
        score = s;
    }

    public String getWord(){
        return word;
    }

    public void setWord(String w){
        word = w;
    }

    @Override
    public int compareTo(Word w){
        if ((this.score) > (w.score)) { return 1; }
        else if ((this.score) < (w.score)) { return -1; }
        return 0;
    }

    public String toString(){
        return ("{" + this.word + "," + this.score + "}");
    }
}

Any help would be appreciated, thank you!

You're creating two different objects. Just because their attributes have the same value, they are not necessarily equal. To achive this, you need to override the equals() method in class Word .

Thus, add:

    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        Word other = (Word) obj;
        if (score != other.score)
            return false;
        if (word == null) {
            if (other.word != null)
                return false;
        } else if (!word.equals(other.word))
            return false;
        return true;
    }

Eclipse provides an easy way to do this (semi-)automatically. Open your Word class, select Source -> Generate hashCode() and equals()... Select attributes that should be considered when checking two Word objects for equality.

Also, you should oderride hashCode() . Related questions:

By the way: Might be a copy&paste issue, but implemented methods from interfaces are not being annotated with @Override (as your compareTo() is). @Override annotation would be appropriate for toString() since you override the toSting() -method of class Object .

From @Override Javadoc:

Indicates that a method declaration is intended to override a method declaration in a supertype.

JUnit's assertEquals depends on you correctly implementing Object.equals(Object) , which you didn't do. Implement equals(Object) in Word to make this work.

Use Lombok to generate the equal and hashcode method. Then it will work. Your code will also become clean by using Lombok annotations.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM