Java의 assertEquals 메소드는 신뢰할 수 있습니까?


199

==두 가지를 비교할 때 문제가 있음을 알고 Strings있습니다. String.equals()더 나은 접근 방법 인 것 같습니다 . 글쎄, 나는 JUnit 테스트를하고 있으며 내 성향은을 사용하는 것 assertEquals(str1, str2)입니다. 이것은 두 개의 문자열에 동일한 내용이 들어 있다고 주장하는 신뢰할 수있는 방법입니까? 나는을 사용할 assertTrue(str1.equals(str2))것이지만, 예상되는 실제 값과 실패한 값을 보는 이점을 얻지 못합니다.

관련 메모에서 누구나 문제를 명확하게 설명하는 페이지 또는 스레드에 대한 링크가 str1 == str2있습니까?


1
확실하지 않은 경우 코드 또는 Javadoc을 읽을 수 있습니다. BTW 테스트하려는 경우 assertSame을 사용할 수있는 것과 동일한 개체입니다.
Peter Lawrey 2009

2
str1 및 str2가 널인 경우 assertEquals ()는 true이지만 assertTrue (str1.equals (str2))는 예외를 발생시킵니다. 첫 번째 예는 str1 및 str2의 내용과 같은 유용한 오류 메시지도 인쇄하지만 두 번째 예는 그렇지 않습니다.
피터 로리

답변:


274

당신은해야한다 항상 사용 .equals()비교할 때 Strings자바.

JUnit은 .equals()메소드에서 동등성을 판별하기 위해 메소드를 호출합니다 assertEquals(Object o1, Object o2).

따라서을 사용하는 것이 안전 assertEquals(string1, string2)합니다. ( Strings는 Objects 이므로 )

여기에 좋은 유래의 질문에 대한 링크입니다 사이의 차이점에 대한 ==.equals().


12
두 문자열이 모두 null 인 경우 IIRC assertEquals ()가 성공합니다. 이것이 원하는 것이 아니라면 assertNotNull ()도 호출하십시오.
finnw

10
또한 ==를 테스트하려면 assertSame ()
james

7
나는 항상 말하지 않을 것이다 . 때로는 문자열에 대해서도 참조 평등이 바람직합니다.
Karu

30

assertEqualsequals비교 방법을 사용합니다 . 연산자 assertSame를 사용 하는 다른 assert가 있습니다 ==.

==문자열과 함께 사용해서는 안되는 이유를 이해하려면 무엇을해야하는지 이해해야합니다 ==. ID 확인을 수행합니다. 즉, a == b검사가 있는지 ab받는 참조 동일한 개체 . 언어에 내장되어 있으며 다른 클래스에서 동작을 변경할 수 없습니다. 반면 equals에이 메소드는 클래스에 의해 대체 될 수 있습니다. 기본 동작 ( Object클래스에서)은 ==연산자를 사용하여 ID 확인을 수행하는 것이지만을 포함하여 많은 클래스 String는이를 대신하여 "동등성"확인을 수행하도록이를 재정의합니다. 의 경우 동일한 객체를 String확인 a하고 b참조하는 대신a.equals(b) 그들이 참조하는 객체가 모두 정확히 동일한 문자를 포함하는 문자열인지 확인합니다.

유추 시간 : 각 String물체가 무언가로 쓰여진 종이 라고 상상해보십시오 . "Foo"가 적힌 종이와 "Bar"가 적힌 종이가 있다고 가정 해 봅시다. 처음 두 장의 종이를 가져 와서 ==비교하는 데 사용 하면 false본질적으로 "이 두 장의 종이입니까?"라고 묻기 때문에 반환됩니다 . 종이에 쓰여진 내용을 볼 필요조차 없습니다. 내가 한 장이 아닌 두 장의 종이를 준다는 사실은 그것을 반환한다는 것을 의미합니다 false. equals그러나을 사용 하면이 equals메서드는 두 장의 종이를 읽고 동일한 내용 ( "Foo")을 말하는 것을 확인하므로 반환 true됩니다.

문자열과 혼동되는 부분은 Java에 "인터 닝"문자열이라는 개념이 있으며 이는 코드의 모든 문자열 리터럴에서 (실제적으로) 자동으로 수행된다는 것입니다. 즉, 코드에 두 개의 동등한 문자열 리터럴이 있으면 (다른 클래스에 있더라도) 실제로는 동일한 String객체를 참조 합니다. 따라서 ==운영자 true가 예상보다 자주 반환 합니다.


"즉, a == b는 a와 b가 동일한 객체인지 확인합니다." 기술적으로 a와 b가 참조이기 때문에 a와 b가 같은 객체를 참조하는지 확인합니다. 내가 잘못한 경우가 아니면
bob

@ user1903064가 맞습니다. 기본이 아닌 변수는 Java로만 참조를 포함 할 수 있기 때문에 이에 대해 이야기 할 때 추가적인 간접 수준을 건너 뛰는 것이 일반적이지만이 경우보다 명시적인 것이 유리하다는 데 동의합니다. 답변을 업데이트했습니다. 제안 해 주셔서 감사합니다!
Laurence Gonsalves 2

7

간단히 말해서, 동일한 문자를 포함하지만 다른 메모리 위치에있는 다른 객체 인 두 개의 String 객체를 가질 수 있습니다. == 연산자는 두 개의 참조가 동일한 객체 (메모리 위치)를 가리키는 지 확인하지만 equals () 메서드는 문자가 같은지 확인합니다.

일반적으로 두 개의 문자열이 동일한 메모리 위치를 가리키는 지 여부가 아니라 동일한 문자를 포함하는지 확인하는 데 관심이 있습니다.


4
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);
    }
}

3

예, 테스트에 항상 사용됩니다. 테스트 프레임 워크는 이와 같은 비교를 위해 .equals ()를 사용합니다.

아래는 "문자열 평등 실수"를 설명하는 링크입니다. 기본적으로 Java의 문자열은 객체이며 객체 동등성을 비교할 때 일반적으로 내용이 아닌 메모리 주소를 기준으로 비교됩니다. 이로 인해 두 문자열은 내용이 동일하더라도 동일한 주소를 차지하지 않으므로 인쇄시 동일하게 보이더라도 올바르게 일치하지 않습니다.

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


3

JUnit assertEquals(obj1, obj2)은 실제로 호출 obj1.equals(obj2)합니다.

도있다 assertSame(obj1, obj2)하는 않습니다 obj1 == obj2(즉, 확인 obj1obj2참조하는하는 동일한 인스턴스) 당신은 피하려고하는지이다.

넌 괜찮아


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.