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'
Related
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);
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.
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.
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.
This might be a silly question. I'm learning objective C (iOS) by studying the code and I came across the expression
[InstanceName class];
What does it do?
I tried to search for class method but It just pops up difference between class method and instance method etc. I guess it might give some sort of class object but I have no idea what is the purpose of the statement.
the original code is Sample Facebook App (scrumptious) using FB SDK....
If you see something like this as a standalone expression....
[InstanceName class];
... then the code is most likely forcing the execution of the +initialize method on said class. The first time any method is invoked on a class, the +initialize method will be invoked prior by the runtime. So, have a look at InstanceName and see if it has a +initialize method.
Note that forcing +initialize to execute in this fashion is a sure sign of bad design. +initialize should never need to be forced like this and should not have execution order dependencies.
There is a legitimate additional reason why this line of code might exist. By referring to InstanceName with a hard reference, it'll force the linker to link in all symbols in the library. (If you don't have a hard reference to at least one symbol in a library -- a .a -- some linkers will simply drop the library from the link unit entirely.)
It gets the class of the object.
So for instance if InstanceName is an instance of class Foo
[InstanceName class]; will return Foo, in a variable of type Class
You can use class_getClassName to get an NSString from this class to log it.
class is a method inherited from NSObject. It lets you get the instance of the class object representing the class of the instance on which the method is called.
It can be used to examine the metadata of the current object. For example, you can use class method to determine if a given object is of a particular class:
if ([sender isKindOfClass:[UIButton class]]) {
...
}
It returns the class of the object. Suppose you have an array of UIView subclasses you created and you want to perform some action only to those who belong to a certain class. You could loop through the array and check for each object's class:
for (id view in myViews) {
if ([view isKindOfClass:[MyUIViewSubclass class]]) {
// Do something
}
}