There is no simple answer to this question, without thinking about what OCMock is for and what kind of test design paradigm it implies.
short version : you should not check this first. Tests should treat the tested methods as a black box, but only compare and verify input and output.
Longer version : you are trying to test a side effect, mainly because makeNoise does not do anything that HelloWorldClass even registers (or “sees”). Or put it more positively: as long as makeNoise correctly tested in tests written for AnotherClass , you do not need to check this simple call.
The example you provide may be a bit confusing, as it is obvious that this leaves nothing meaningful for testing in the mobileTest unit test, but given that you can also ask why transfer a simple NSLog call to another class (first of all testing for NSLog call is pointless). Of course, I understand that you just use this as an example and imagine a more complex other scenario in which you want to make sure that a particular call is occurring.
In such a situation, you should always ask yourself: "Is this the right place to check it?" If the answer is yes, which should imply that any message that you want to test for the call should go to an object that is not entirely within the scope of the class being tested. For example, it could be a singleton (some global logging class) or a class property. Then you have a descriptor, an object that you can correctly deride (for example, set the property of a partially mocked object) and check.
In rare cases, which can lead to the fact that you provide a descriptor / property for the object, just so that it can be replaced with a layout during testing, but this often indicates a suboptimal class and / or method (I am not going to say that it’s always the case , although).
Let me give you three examples from one of my projects to illustrate something similar to your situation:
Example 1 : checking that the URL is open (in mobile Safari): this is basically checking that openURL: is called on the shared instance of NSApplication , something very similar to what you have in mind. Note that the shared instance is not "completely within the scope of the tested methods" because it is single "
id mockApp = OCMPartialMock([UIApplication sharedApplication]); OCMExpect([mockApp openURL:[OCMArg any]]); // call the method to test that should call openURL: OCMVerify([mockApp openURL:[OCMArg any]]);
Note that this works because of the specificity of the partial layout: even if openURL: not called in mock, since mock is related to the same instance used in the test method, it can still check the call, If the instance was not a single, which would not work, you could not create a layout from the same object that is used in your method.
Example 2 : an adapted version of your code that allows you to "capture" an internal object.
@interface HelloWorldClass @property (nonatomic, strong) AnotherClass *lazyLoadedClass; @end @implementation HelloWorldClass() // ... // overridden getter -(AnotherClass *)lazyLoadedClass { if (!_lazyLoadedClass) { _lazyLoadedClass = [[AnotherClass alloc] init]; } return _lazyLoadedClass; } -(void)mobileTest{ [self.lazyLoadedClass makeNoise]; } @end
And now the test:
-(void)testMobileTest{ HelloWorldClass *helloWorldObject = [[HelloWorld alloc] init]; id mockObject = OCMPartialMock([helloWorldObject lazyLoadedClass]); OCMExpect([mockObject makeNoise]); [helloWorldObject mobileTest]; OCMVerify([mockObject makeNoise]); }
The lazyLoadedClass method can even be included in the class extension, i.e. "private". In this case, just copy the appropriate category definition to the top of the test file (usually I do this and yes, this is IMO, the real case is mostly “testing private methods”). This approach makes sense if AnotherClass is more complex and requires complex configuration or something else. Usually such things lead to the scenario that you have in the first place, i.e. Its complexity makes it not only an assistant than can be thrown out after the method is completed. it will also lead you to a better code structure, since you have your own initializer in a separate method and can also check this accordingly.
Example 3 If AnotherClass has a non-standard initializer (for example, a singleton, or it comes from the factory class), you can drown it and return a mocking object (this is a kind of brain node, but I used it)
@implementation AnotherClass() // ... -(AnotherClass *)crazyInitializer { // this is in addition to the normal one... return [[AnotherClass alloc] init]; } @end -(void)testMobileTest{ HelloWorldClass *helloWorldObject = [[HelloWorld alloc] init]; id mockForStubbingClassMethod = OCMClassMock([AnotherClass class]); AnotherClass *baseForPartialMock = [[AnotherClass alloc] init]; // maybe do something with it for test settup id mockObject = OCMPartialMock(baseForPartialMock); OCMStub([mockForStubbingClassMethod crazyInitializer]).andReturn(mockObject); OCMExpect([mockObject makeNoise]); [helloWorldObject mobileTest]; OCMVerify([mockObject makeNoise]); }
It looks stupid and I admit it is pretty ugly, but I used it in some tests (you know this point in the project ...). Here I tried to simplify the reading and use two layouts, one of which drowned out the class method (i.e., the Initializer) and the one that then returned. The mobileTest method should obviously use AnotherClass custom initializer, then it gets a mocking object (for example, a cuckoo egg ...). This is useful if you want to specifically prepare the object (which is why I used the partial layout here). I'm actually not sure if you could do this with just one mock class (close the class method / initializer on it so that it returns, and then expect the method you want to check to be called) ... as I already have said tying.