Comparing [class] does not work?

199 Views Asked by At

I have a unit test:

- (void)testFetchTrackByTrackIdIsATrack
{
    [self addTrackWithSongId:@"123"];
    Track *fetchedTrack = [self.library trackByTrackId:@"123"];
    assertThat(fetchedTrack, instanceOf([Track class]));
}

Which fails with:

file:///Users/elliot/Development/Hark/HarkTests/TestLibrary.m: test failure:
-[TestLibrary testFetchTrackByTrackIdIsATrack] failed: Expected an instance
of Track, but was Track instance <Track: 0x6180001077d0>

I have several other tests that use the same instance checking on different classes that work - but I can't workout why this doesn't work. Delving deeper:

- (void)testFetchTrackByTrackIdIsATrack
{
    [self addTrackWithSongId:@"123"];
    Track *fetchedTrack = [self.library trackByTrackId:@"123"];
    Class c1 = [fetchedTrack class];
    Class c2 = [Track class];
}

Debugger reports:

c1  Class   Track           0x0000000100012fe0
c2  Class   0x1000b3eb8     0x00000001000b3eb8

Notice how it can't see that [Track class] is a class of type Track? When I apply this same logic to other unit tests that are passing they both report the correct class name.

It feels like it doesn't have the class metadata at runtime, but why?

Some more cases:

assertTrue(c1 == c2);                                   // FAIL
assertThat([fetchedTrack classDescription],
  equalTo([Track classDescription]));                   // PASS
assertTrue([fetchedTrack isKindOfClass:[Track class]]); // FAIL
1

There are 1 best solutions below

6
On

There are any number of reasons why the class's address may not be constant over time and most of them boil down to the use of Key-Value Observing.

When an instance is observed, the runtime (the Foundation framework, really) composes a new class that is a subclass of the instance's original class that contains the observation mechanisms.

This results in the inability to use pointer comparison. It also means that certain types of introspection of the class will fail to yield expected results.

In short; use the isKindOfClass: and isMemberOfClass: methods for all such tests and never use pointer equality testing (for this or for comparing instances, in general).