XCTAssertEqual fails to compare two string values?
Asked Answered
S

4

85

I added a simple unit test to test my string extension. But it fails. What I am I doing wrong here?

From what I know XCTAssertEqual is testing value and not the object itself?

The third line btw, says the string are equal, but XCTAssertEqual says they're not.

- (void) testInitialsFromFullname {
    NSString *firstNickName = @"Mike Kain";
    NSString *expectedResult = @"MK";
    NSLog(@"Equal:%@", [[firstNickName initialsFromString] isEqualToString:expectedResult] ? @"YES" : @"NO");

    XCTAssertEqual(expectedResult, [firstNickName initialsFromString], @"Strings are not equal %@ %@", expectedResult, [firstNickName initialsFromString]);
}
Spleenwort answered 19/10, 2013 at 8:57 Comment(1)
This was a perfectly reasonable question, and I ran into the same issue when I first started with XCUnit. The accepted answer helped as well.Boarhound
R
177

From the documentation of XCTAssertEqual:

Generates a failure when a1 is not equal to a2. This test is for C scalars, structs and unions.

You should use XCTAssertEqualObjects (which uses isEqual: internally) or something like:

XCTAssertTrue([[firstNickName initialsFromString] isEqualToString:expectedResult],
              @"Strings are not equal %@ %@", expectedResult, [firstNickName initialsFromString]);
Randall answered 19/10, 2013 at 9:11 Comment(7)
It seems that if you XCTAssertEqualObjects() two NSString objects they are compared with isEqualToString: automatically.Calvinna
It uses -isEquals: under the hood all the time, but for NSString -isEquals: executes well-known -isEqualToString:. For instance, NSNumber implementation of -isEquals: method uses -isEqualToNumber:.Stamp
Unfortunately despite still being in the docs, as of Xcode 7.2 XCTAssertEqualObjects is no longer available.Southerner
XCAssertEqual(a, b) works just fine in XCode 7. This answer is not correct anymore.Trilingual
XCTAssetEqualObjects is available in Xcode 8.0 and works for comparing NSStrings.Blastogenesis
Using XCTAssetEqualObjects is better because if the test is failed, it will throw exactly the wrong string. XCTAssertTrue throws just only: "Oh it's not true"Aixenprovence
This is actually a test smell. Don't do this.Gnawing
M
15

I've just had a similar issue which might help someone.

I have a Float extension function which returns a string. The following test fails:

testValue = 0.01
XCTAssertEqual(testValue.formattedForCost(), "0,01 €")

With the following message:

Assertions: XCTAssertEqual failed: ("Optional("0,01 €")") is not equal to ("Optional("0,01 €")")

Which is rather annoying. However I discovered if I change my test to use the unicode no-break space character:

XCTAssertEqual(testValue.formattedForCost(), "0,01\u{00a0}€")

It passes.

Margit answered 10/10, 2016 at 9:0 Comment(1)
This worked for me too, but there's got to be a better solution.Ironist
M
3

Objective-C Comparing strings

- (void) testStringComparison {
    NSString *first = @"my string";
    NSString *second = @"my string";
    
    NSMutableString *firstMutable = [NSMutableString stringWithString:first];

    //== comparing addresses of the objects(pointer comparison)
    //`first` and `second` has the same address it is a compiler optimization to store only one copy
    XCTAssertTrue(first == second);
    XCTAssertFalse(first == firstMutable);
    
    XCTAssertEqual(first, second);
    XCTAssertNotEqual(first, firstMutable);
    XCTAssertEqualObjects(first, firstMutable);
    XCTAssertTrue([first isEqualToString:firstMutable]);
}
Megalo answered 30/3, 2020 at 17:48 Comment(2)
do we expect all the assert calls result in true? I'm new into the unit testingCarlita
@gomozor, XCTAssertTrue expect TRUE, XCTAssertFalse expect FALSE. Expect means that a unit test is passedMegalo
S
0

I had the same issue with string values apparently not being equal. I had to use the String .compare func, however, be aware that if you are testing string formatted for different Locales, you need to also pass the locale into the compare method. I assume that there are locale specific unicode characters in the string?

let expected = "9,32 EUR"

let actual = formattedPrice(for: price)

let locale = Locale(identifier: "fr_FR")

XCTAssertTrue(expected.compare(actual, locale: locale) == .orderedSame)
Sander answered 26/1 at 11:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.