简体   繁体   中英

How can I write a unit test that checks that my properties are released in dealloc on iOS?

I'm pretty new to TDD and unit testing and I'm giving it a try in a side project.

And I'm kinda stuck in unit testing the dealloc method.

We all know it is a good practice to release custom properties and set them to nil in the dealloc:

-(void) dealloc{
  [myProperty release];
  myProperty = nil;
  [super dealloc];
}

How could I write a unit test that check this behaviour?

Obviously, this does not work:

[myObject release]
STAssertNil(myObject.myProperty,@"myProperty should be released and set to nil in dealloc")

Any suggestion? thanks !

Assuming you could do the above, what would you actually be testing? Here is what i think:

  1. testing that -release decrements the retainCount

  2. testing that when retainCount reaches zero NSObject's Garbage Collection mechanism calls -dealloc

  3. testing that when -dealloc is called, myProperty is released

This is the wrong granularity for a unit test, points one and two are not your business to test - assume it is unit tested by apple. So, the only bit of the above that is a unit test is:

testing that when -dealloc is called, myProperty is released

Now, this piece of code (quite rightly) has no logic whatsoever and produces no output. So, i believe that unit testing it is actually paranoid and unnessesary (akin to testing that the compiler actually works).

But if i did want to test it i would do it like so:

OCMockObject *mockProperty = MOCK(NSObject);
[[mockProperty expect] release];
myObject.myProperty = mockProperty;
[myObject dealloc];
[mockProperty verify];

Obviously you should never normally directly call -dealloc, but if you wanted to unit-test -dealloc that is exactly what you should do (or it isn't a unit-test). Given that this is extremely bad practise and the test gains you very little, i don't think you should bother.

This is definitely overkill for TDD. You want to test unit functionality with TDD and catch simpler errors with another tool. (I'm just worried that if you start writing tests at this level of detail, you will never be able to finish a project.) I don't personally consider refcounts to be part of a unit's interface, so for me, it's just outside the scope of the unit test itself.

I suggest using instrumentation. Run through all your tests and instrument them (on OS X, we use the "Instruments" app since 10.5, on Linux we use Valgrind). The instrumentation will tell you whether all your objects are freed or whether you have a memory leak. I also recommend making sure that you test error paths — in my experience, most memory leaks happen when other errors happen at the same time.

I use a custom testing script which runs through all the tests, and it has an option flag for instrumenting them. I don't always instrument them because the full level of instrumentation slows down the tests quite a bit.

However, if you want to do things the hard way:

someProp = [[... alloc] init];
assert([someProp retainCount] == 1);
[myObject setSomeProp:someProp];
assert([someProp retainCount] > 1); // NOT == 2, that would be wrong
[myObject release];
assert([someProp retainCount] == 1);

Apologies for the archaic, Obj-C 1.0 style.

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