[java] Is Java's assertEquals method reliable?

I know that == has some issues when comparing two Strings. It seems that String.equals() is a better approach. Well, I'm doing JUnit testing and my inclination is to use assertEquals(str1, str2). Is this a reliable way to assert two Strings contain the same content? I would use assertTrue(str1.equals(str2)), but then you don't get the benefit of seeing what the expected and actual values are on failure.

On a related note, does anyone have a link to a page or thread that plainly explains the problems with str1 == str2?

This question is related to java string junit junit4

The answer is


The JUnit assertEquals(obj1, obj2) does indeed call obj1.equals(obj2).

There's also assertSame(obj1, obj2) which does obj1 == obj2 (i.e., verifies that obj1 and obj2 are referencing the same instance), which is what you're trying to avoid.

So you're fine.


assertEquals uses the equals method for comparison. There is a different assert, assertSame, which uses the == operator.

To understand why == shouldn't be used with strings you need to understand what == does: it does an identity check. That is, a == b checks to see if a and b refer to the same object. It is built into the language, and its behavior cannot be changed by different classes. The equals method, on the other hand, can be overridden by classes. While its default behavior (in the Object class) is to do an identity check using the == operator, many classes, including String, override it to instead do an "equivalence" check. In the case of String, instead of checking if a and b refer to the same object, a.equals(b) checks to see if the objects they refer to are both strings that contain exactly the same characters.

Analogy time: imagine that each String object is a piece of paper with something written on it. Let's say I have two pieces of paper with "Foo" written on them, and another with "Bar" written on it. If I take the first two pieces of paper and use == to compare them it will return false because it's essentially asking "are these the same piece of paper?". It doesn't need to even look at what's written on the paper. The fact that I'm giving it two pieces of paper (rather than the same one twice) means it will return false. If I use equals, however, the equals method will read the two pieces of paper and see that they say the same thing ("Foo"), and so it'll return true.

The bit that gets confusing with Strings is that the Java has a concept of "interning" Strings, and this is (effectively) automatically performed on any string literals in your code. This means that if you have two equivalent string literals in your code (even if they're in different classes) they'll actually both refer to the same String object. This makes the == operator return true more often than one might expect.


public class StringEqualityTest extends TestCase {
    public void testEquality() throws Exception {
        String a = "abcde";
        String b = new String(a);
        assertTrue(a.equals(b));
        assertFalse(a == b);
        assertEquals(a, b);
    }
}

In a nutshell - you can have two String objects that contain the same characters but are different objects (in different memory locations). The == operator checks to see that two references are pointing to the same object (memory location), but the equals() method checks if the characters are the same.

Usually you are interested in checking if two Strings contain the same characters, not whether they point to the same memory location.


Yes, it is used all the time for testing. It is very likely that the testing framework uses .equals() for comparisons such as these.

Below is a link explaining the "string equality mistake". Essentially, strings in Java are objects, and when you compare object equality, typically they are compared based on memory address, and not by content. Because of this, two strings won't occupy the same address, even if their content is identical, so they won't match correctly, even though they look the same when printed.

http://blog.enrii.com/2006/03/15/java-string-equality-common-mistake/


"The == operator checks to see if two Objects are exactly the same Object."

http://leepoint.net/notes-java/data/strings/12stringcomparison.html

String is an Object in java, so it falls into that category of comparison rules.


Examples related to java

Under what circumstances can I call findViewById with an Options Menu / Action Bar item? How much should a function trust another function How to implement a simple scenario the OO way Two constructors How do I get some variable from another class in Java? this in equals method How to split a string in two and store it in a field How to do perspective fixing? String index out of range: 4 My eclipse won't open, i download the bundle pack it keeps saying error log

Examples related to string

How to split a string in two and store it in a field String method cannot be found in a main class method Kotlin - How to correctly concatenate a String Replacing a character from a certain index Remove quotes from String in Python Detect whether a Python string is a number or a letter How does String substring work in Swift How does String.Index work in Swift swift 3.0 Data to String? How to parse JSON string in Typescript

Examples related to junit

Eclipse No tests found using JUnit 5 caused by NoClassDefFoundError for LauncherFactory How to resolve Unneccessary Stubbing exception JUnit 5: How to assert an exception is thrown? How do I mock a REST template exchange? Class Not Found: Empty Test Suite in IntelliJ Unable to find a @SpringBootConfiguration when doing a JpaTest Failed to load ApplicationContext (with annotation) Example of Mockito's argumentCaptor Mockito - NullpointerException when stubbing Method Spring jUnit Testing properties file

Examples related to junit4

Mockito: Mock private field initialization java.lang.Exception: No runnable methods exception in running JUnits How to write JUnit test with Spring Autowire? How to run JUnit tests with Gradle? Difference between @Before, @BeforeClass, @BeforeEach and @BeforeAll How to test that no exception is thrown? Failed to load ApplicationContext for JUnit test of Spring controller How does Junit @Rule work? maven error: package org.junit does not exist How do I assert an Iterable contains elements with a certain property?