OCMock stub class method for all invocations - ios

I have a Utility class with some class methods.
#interface DataValidator : NSObject
+ (BOOL)foo;
#end
The usage of the class is inside other classes, say NetworkManager, DBHandler etc. And since there are no instance methods in Utility class, there is no need for any class to create an instance of Utility class. Rather they directly make the calls like this
[Utility foo];
When writing tests for NetworkManager/DBHandler, is it possible to mock Utility and stub foo so all calls made to it return the mocked response.
If I mock the Utility class in NetworkManager class tests, the NetworkManager code still calls original method instead of the stubbed one.
This only works if I directly call [Utility foo] from inside the tests, but thats not useful in my case.

Looks like OCMock 3 has a way to mock Class methods:
http://ocmock.org/reference/#mocking-class-methods
An example from that page:
id classMock = OCMClassMock([SomeClass class]);
OCMStub([classMock aClassMethod]).andReturn(#"Test string");
// result is #"Test string"
NSString *result = [SomeClass aClassMethod];

I wasn't able to achieve this. What I ended up doing is converting the class methods to instance methods and then mocking those.

Related

Inject dependency for singleton objective c class in swift test cases

I have one singleton class written in Objective C which is being used in helper class which is also written in Objective C. I am writing a test case for the helper class, but instead of making changes directly to singleton class methods, I want to create a mock singleton class, but I'm not sure how to do that. I don't want to make any changes in helper class either like creating a init method which takes singleton class object and initialise it like mention on other threads for test cases for singleton class.
Thanks for looking the question.
You can use OCMock for mocking objects in your project OCMock
Then you can mock your singleton like this
YOUR_SINGLETON *mock = OCMClassMock([YOUR_SINGLETON class]);
And stub function like this
OCMStub([(id) mock YOUR_FUNCTION:PARAMETER]).andReturn(VALUE_FOR_TEST_CASE);

Testing void methods using OCMock in iOS

I am trying to write a test case for a method in Objective-C class which returns void. The method mobileTest just creates another object of class AnotherClass and calls a method makeNoise. How to test this ?
I tried to use OCMock to create test this. Created a mock object of AnotherClass, and called mobileTest method. Obviously, the OCMVerify([mockObject makeNoise]) won't work, as I am not setting this object anywhere in the code. So, how to test in such cases ?
#interface Hello
#end
#implementation HelloWorldClass()
-(void)mobileTest{
AnotherClass *anotherClassObject = [AnotherClass alloc] init];
[anotherClassObject makeNoise];
}
#end
#interface AnotherClass
#end
#implementation AnotherClass()
-(void) makeNoise{
NSLog(#"Makes lot of noise");
}
#end
Test case for the above is as follows :
-(void)testMobileTest{
id mockObject = OCMClassMock([AnotherClass class]);
HelloWorldClass *helloWorldObject = [[HelloWorld alloc] init];
[helloWorldObject mobileTest];
OCMVerify([mockObject makeNoise]);
}
There's not a simple answer to this without going a bit into what OCMock is meant for and what test design paradigm it implies.
The short version is: You should not test this like that in the first place. Tests should treat the tested methods as a black box and only compare & verify input vs output.
Longer version: You're trying to test for a side effect, basically, since makeNoise doesn't do anything that the HelloWorldClass even registers (or "sees"). Or to put it in a more positive way: As long as makeNoise is properly tested in the tests written for AnotherClass you don't need to test that simple call.
The example you provide may be a bit confusing, since obviously that doesn't leave anything meaningful to test in mobileTest's unit test, but considering that you might also question why to outsource the simple NSLog call to another class in the first place (and testing for an NSLog call is kind of pointless, of course). Of course I understand you're just using this as an example and envision a more complex different scenario in which you want to ensure that a specific call happens.
In such a situation, you should always ask yourself "Is this the correct place to verify this?" If the answer is "yes" that should imply that whatever message you want to test to be called needs to go to an object that's not completely inside the scope of the tested class only. For example, it could be a singleton (some global logging class) or a property of the class. Then you have a handle, an object that you can properly mock (for example, set the property to a partially mocked object) and verify.
In rare cases that might lead you to provide a handle/property for an object simply to be able to replace it with a mock during testing, but that often indicates a sub-optimal class and/or method design (I'm not gonna claim that's always the case, though).
Let me provide three examples from one of my projects to illustrate something similar to your situation:
Example 1: Verifying that an URL is opened (in mobile Safari): This is basically verifying that openURL: is called on the shared NSApplication instance, something very similar to what you have in mind. Note that the shared instance is not "completely inside the tested methods scope" as it is a singleton"
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 due to the specifics of a partial mock: Even though openURL: is not called on the mock, because the mock has a relationship to same instance that is used in the tested method it can still verify the call. If the instance weren't a singleton that would not work, you would not be able to create the mock from the same object that is used in your method.
Example 2: Adapted version of your code to allow "grabbing" the 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 might even be in a class extension, i.e. "private". In that case, just copy the according category definition to the top of your test file (I usually do this, and yes, this is, IMO, a valid case of basically "testing private methods"). This approach makes sense if AnotherClass is more complex and requires elaborate setup or something. Usually stuff like this then leads to the scenario you have in the first place, i.e. its complexity makes it to more than just a helper than can be thrown away after the method finishes. this will then also lead you to better code structure, since you have its initializer in a separate method and can test that accordingly, too.
Example 3: If AnotherClass has a non-standard initializer (like a singleton, or it comes from a factory class) you can stub that and return a mocked object (this is kind of a brain-knot, but I have 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]);
}
This looks kind of stupid and I admit it's plain ugly, but I have used this in some tests (you know that point in a project...). Here I tried to make it easier to read and used two mocks, one to stub the class method (i.e. the initializer) and one that then is returned. The mobileTest method should then obviously use the custom initializer of AnotherClass, then it gets the mocked object (like a cuckoo's egg...). This is useful if you want to specially prepare the object (which is why I used a partial mock here). I am actually not sure atm if you could also do this with only one class mock (stub the class method/initializer on it so it returns itself, then expect the method call you want to verify)... as I said, brain-knotting.

Stub a class method on an OCMPartialMock?

I’m using OCMock, and attempting to test a class with two class methods. I’d like to stub one in order to write a test for the other, so I’d normally use an OCMPartialMock. However, if I do this, I can’t call the class method since OCMPartialMock uses an instance of the class, not the class itself. If I use OCMClassMock, it’ll lose the implementation of the method I want to test.
In summary: I have two class methods, and I’d like to stub one but retain the ability to call the other, using OCMock. How can I achieve this?
Found the answer: need to use an OCMClassMock, and since it’s swizzled the class, call the other class method on the class itself, not on my mocked id version.
sample code:
#interface MyClass: NSObject
+ (void)hello;//this is a class method
#end
id mock = OCMClassMock([MyModel class]);
[OCMStub([mock hello]) andDo:^(NSInvocation *invocation) {
NSLog(#"hello everyone");
}];
[MyModel hello]; //it will print 'hello everyone'

How to spy on a class method in Kiwi?

I've looked through various examples with class mocking, like these:
https://groups.google.com/forum/#!topic/kiwi-bdd/hrR2Om3Hv3I
https://gist.github.com/sgleadow/4029858
Mocking expectations in Kiwi (iOS) for a delegate
The class Test has a class method fetch.
What I am trying to achieve is to see if a method from a class gets called during the work of the class I want to test.
What I do:
it(#"test", ^{
id mock = [KWMock mockForClass:[Test class]];
[[mock should] receive:#selector(fetch)];
Repository *rep = [[Repository sharedInstance] rep]; //method `rep` invokes [Test fetch] at some point
});
And the test fails with the following error:
[FAILED], expected subject to receive -fetch exactly 1 time, but received it 0 times
What am I doing wrong? How the spy mechanism should work on class methods?
[[Test should] receive:#selector(fetch)];
Thats how you should check it since its a method class not an instance class you dont need a mocked class object. The autocompletion when you write might not show it so you have to force this.

Objective-C call a class method in runtime which the class is private

I got a .framework file, and I use class-dump to know there is a class named ABC inside and don't expose anything, and ABC have a useful method for me, so I wonder know can I call ABC's method dynamic by Objective-C runtime.
Wait for your help!
To create an instance of class if by it's name use NSClassFromString:
Class myPrivateClass = NSClassFromString(#"MyPrivateClass");
myPrivateClass *myPrivateObj = [myPrivateClass new];
Now that you have the instance of the class call the select, to make it easier you can cast the instance to NSObject
[(NSObject *)myPrivateClass performSelector:#selector(description) withObject:nil];
Or the class method:
[myPrivateClass performSelector:#selector(description)];
Here I'm calling description on the instance and class.

Resources