We are using SUP on our project and everything seems to be working well.
We decided to create a unit test target and write some unit tests, but SUP crashes as soon as the tests start (only on 2.1.3).
Anyone else is having trouble running unit tests in an SUP based app?
Is there a simple way to mock SUP?
All my SUP logic is in a singleton class, so I ended up overriding the shared instance method using a category and prevent the crash using some reflection API, In the rest of the app wherever SUP is needed I create a mock (using OCMock), and assign the expected behavior.
Method originalMethod = class_getClassMethod([MessagingClientLib class], @selector(getInstance));
Method categoryMethod = class_getClassMethod([self class], @selector(mockGetInstance));
originalMethod = class_getClassMethod(NSClassFromString(@"SUPOCHandler"), @selector(getInstance));
categoryMethod = class_getClassMethod(NSClassFromString(@"SUPOCHandler"), @selector(mockInitialize));
return [OCMockObject niceMockForClass:[MySupManager class]];
// Do nothing
That is a really good workaround to make sure that you can actually execute tests. It should be a lot easier than this to test our SUP applications but that is all we have for now.
Just one question: Did you have time to dig deeper on why this crash is happening?
- My first guess was that I wasn't initializing the SUP connection when the unit tests launch. However, I have checked to see that when my main application starts, there is absolutely no SUP logic. In other words, I am not accessing any SUP classes until the user presses a button. As a result, there shouldn't be any difference between when my application launches and when my unit test target (application unit tests) launches. However, the crash only occurs during the unit test launch.
Let me know if you were able to find why the crash only occurs during unit tests.
Also, you would probably know this but you can use 'logic unit tests' as an alternative. Simply create a unit test target of type 'logic tests' and don't include any SUP relevant classes in its Build Phases -> Compile Sources. That way, you can test your model/business logic in isolation.
My code was not accessing any SUP classes (until login button is selected), neither was my unit test. OCUnit loops through all the classes at startup and performs some reflection tasks. The crash was happening while OCUnit was calling "getInstance" on "SUPOCHandler", and that's why I mocked that method.
An yes it was crashing because sup connection was not initialized which was intended because unit test should not have any external dependencies. I'm glad you found this helpful.
Yes, found it very helpful indeed.
I found the Stackoverflow counter-part of this discussion at: http://stackoverflow.com/questions/5332348/ocunit-tests-giving-errors-in-classes-not-being-tested. Take a look when you have the time.
Just thinking about an ideal solution to this problem: I guess it would be a better design from Sybase's part. The coupling between SUPOCHandler and SUPApplication classes in the +initialize: method can probably be prevented.