How can I use OCMock objects with code that calls isKindOfClass? - ios

I'd like to test some code with OCMock.
The innards of the code are calling [NSObject isKindOfClass] on the mock object I'm providing to the code, like so:
if ([object isKindOfClass:[FancyClass class]]) { ...}
However, when I provide an OCMockObject-based mock created like this:
mock = [OCMockObject mockForClass:[FancyClass class]];
it appears that it does not pass the isKindOfClass test.
Any suggestions?

The general rule is that if you're calling isKindOfClass: and you're not passing one of the plist classes (e.g., NSString or NSNumber), You're Doing It Wrong.
If the method does two or more different things depending on which class its argument is, rend it into multiple methods, and test each method separately.
If the method does only one thing, but has to interact with the object differently depending on which class it is, then:
Make a protocol. (Protocols in Obj-C are called “interfaces” in some other OO languages, such as Java.)
Make the many classes all conform to the protocol. If necessary, use categories to add the necessary methods from outside.
Make the method under test check for conformance to the protocol, in place of the current isKindOfClass: check.
Make the method under test use the methods in the protocol.

What about:
[[[mock stub] andReturnValue:OCMOCK_VALUE((BOOL) {YES})] isKindOfClass:[FancyClass class]];

Related

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'

when use protocol not for a delegate in objective-c?

A protocol is a list of method statement , anyone who conforms to it must or may implement it .
In most cases,a delegate's implementation relies on protocol,such as below:
#protocol VSActivateCouponDelegate <NSObject>
-(void)activateCouponSuccessWithActivateType:(ActivateType)type;
#end
My question is protocol's usage scenarios except implementing Delegate ?
For example, any interface that you want to keep generic in terms of not knowing the exact class that will be providing a specific role in some relationship. Delegate is one example of that but any relationship between two classes could use the same approach to abstraction.
Check out NSCopying, NSCoding etc. These are also protocols, but they are not used as delegates.
Let's look at NSCopying for example. If a class conforms to NSCopying, you know that you can call copy on any of its instances (and... copy it ), without even looking at the specific class, you can even pass instances as id<NSCopying> - this makes things more decoupled. For instance NSDictionary only accepts key values that are id<NSCopying>.
To summarize, protocols let you declare behavior without coupling it to a specific class. It doesn't always have to be delegates.
an example would be:
say you have an array of arbitrary objects of arbitrary types. now you want to make sure that all the objects at least have a certain function you can call on all of them to make them do something, then you can make all those objects conform to a protocol that has that method, thus making sure all the objects in that array have that certain functionality.
pseudo code of what that may look like:
#protocol MyProtocol {
- (void) doSomething;
}
//used somewhere
for(MyProtocol object in arrayOfUnknownObjects)
[object doSomething]; //dont know what object's type is but we know it has [doSomething] method

Passing method call through several unrelated classes

This has a sort of Responder Chain feel to it, but the difference there is, the responder chain is a defined operation on views and view controllers specifically.
Well, I need to pass along a method call through several unrelated classes, and being fairly new to Objective-C, i'm not sure if it would be a hack to define a protocol, and then implement that protocol on every class that the call needs to pass through.
For example...
ClassA is the delegate to ClassB.
ClassB is the delegate to ClassC
... hence the 'responder chain' feel.
Does this make sense for the code to pass along a call from C to B to A.
I assume at some point, when the chain gets too long, you'd probably recommend a notification technique instead, but I don't know what that recommended length might be.
#protocol DidSomething
-(void)userDidSomething:(NSString*)something
#end
ClassA <DidSomething>
-(void)userDidSomething:(NSString*)something
{
NSLog(#"The user did something %#",something);
}
ClassB <DidSomething>
-(void)userDidSomething:(NSString*)something
{
[self.delegate userDidSomething:something];
}
ClassC <DidSomething>
-(void)thatWasInteresting
{
[self.delegate userDidSomething:#"Cool"];
}
Nope. Nothing wrong with that. Save for the potential complexity.
You could define it as a protocol, if you want. Or you could define it as a common abstract superclass (if possible).
Protocols are generally the way to go these days and using #optional requires the use of a respondsToSelector: test (or conformsToProtocol:).
All in all, though, you should be very careful about the use of such a pattern. Specifically, it implies a lot about the architecture of your application and, thus, you want to make sure the architecture is sound.
Another alternative is using NSNotificationCenter to post NSNotifications. Object can add themselves as observers. Depending on your needs, this might be a good alternative to passing a message through a chain of delegate.
It is especially useful if more than one object needs to respond to a message.

OCMock test category methods

I may not completely understand mocking as I have a burning question about a very basic scenario. How does one test an instance method of a class OR how does one test a category method for a class?
Consider a class PeerMessage which defines a few properties, etc. I create my own custom category for PeerMessage called Type where I define a method, isTextMessage:. isTextMessage returns a boolean value based on the contents of a PeerMessage. (Please not that this is just an sample type.)
In a test with OCMock, I configure a mock of type PeerMessage and set it's content to some valid value as follows:
id peerMessage = [OCMockObject mockForClass:[PeerMessage class]];
[[[peerMessage stub] andReturn:#"<valid>"] content];
And then assert that peerMessage is a text message:
XCTAssert([peerMessage isTextMessage]);
Considering how mocking works, this results in: 'Unexpected method invoked'. Clearly, as I didn't specify that I was expecting it; neither did I stub it. As I just wanted to verify this API.
How does one test these instance methods (in this case, category instance methods). One way to do this is to redesign the category as follows:
Instead of
- (BOOL)isTextMessage;
do:
+ (BOOL)isTextMessage:(PeerMessage *)message;
But this is to me is very unnatural and I don't feel like writing this code although I don't see anything wrong with it. It doesn't need to be class method. :/
(If my explanation for the question is a bit ambiguous, I'd be happy to update.)
You want to use a partial mock, somehow like this:
id peerMessage = [OCMockObject partialMockForObject:[[PeerMessage alloc] init]];
[[[peerMessage stub] andReturn:#"<valid>"] content];
XCTAssert([peerMessage isTextMessage]);
This way, the real implementation of isTextMessage, the one you want to test, is invoked, but you can still stub out other methods on the object.

Call class method on object of unknown class

I added a set of classes to an array, all which I know have the same superclass:
[array addObject:[Africa class]];
[array addObject:[Brazil class]];
[array addObject:[France class]];
Later, I want to get the class object and call a superclass class method on it. Something like this:
Class class = [array objectAtIndex:1];
(Country class) specificClass = class;
I've tried a variation of different ideas, but can't figure out how to put that last line in code.
If I get you right you want a variable pointing to a class object, statically typed to a concrete class.
This not possible in Objective-C; there are no strongly typed class pointers. Class class is the best you can do.
You can send any known class method to a Class typed variable...
[class alloc];
[class defaultManager];
[class myCommonClassMethod];
... without making the compiler complain. Of course some of the examples might fail at runtime.
With a proper design pattern, you shouldn't need to know which country you are working with.
Start by creating an AbstractCountry class that declares (and provides stub implementations) of all the methods your countries need to generically respond to (i.e. countries can be more specific).
Then subclass that AbstractCountry for each individual country.
Then:
AbstractCountry *countryClass = [array objectAtIndex:n];
If you need behavior that only exists on a single country, then either push a stub implementation up (which wouldn't be terribly elegant) or test for response to selector (also not elegant) or cast appropriately (fragile).
Of course, all of this begs the question of why you have classes for this and not instances (though the instance design would be the same; consider something like UIControl and all the subclasses -- the control provides the abstract behavior of controls whereas the subclasses implement specific kinds of controls by oft overriding the abstract methods).
Usually in Objective-C you would call a method like so:
[class someMethod];
So in your case, let's pretend that your superclass (I'm assuming "Country") has a method to set the population or something, it would look like:
[Africa setPopulation:someInteger];

Resources