OCMock: Mocking protocols with excluding optional methods - objective-c

I'm using OCMock for creating mocks in my tests for my iOS app, and I'd like to create mocks of protocols that don't implement all of the optional methods.
If it's not clear what I mean... here's some code:
// Protocol definition
#protocol MyAwesomeProtocol
- (void)doThatRequiredThing;
#optional
- (void)doThatOptionalThing;
#end
...
// In a test
id mock = [OCMockObject mockObjectForProtocol:#protocol(MyAwesomeProtocol)];
// This should return YES:
[mock respondsToSelector:#selector(doThatRequiredThing)];
// This should return NO:
[mock respondsToSelector:#selector(doThatOptionalThing)];

I hit this limitation as well. The basic idea is to override respondsToSelector: (which CANNOT be reliably mocked by OCMock).
I made the following class which does this for you.
You can then use it as follows:
extend GCOCMockOptionalMethodSupportingObject, and implement your protocol
#interface GCTestDelegate : GCOCMockOptionalMethodSupportingObject <GCDelegate>
#end
#implementation GCTestDelegate
//required methods
- (void)requiredMethod{
}
#end
// create your testdelegate
self.classBeingTested.delegate = [OCMock partialMockForObject:[GCTestDelegate new]];
[self.classBeingTested.delegate markSelectorAsImplemented:#selector(optionalMethod:)];
[[self.classBeingTested.delegate expect] optionalMethod:self.classBeingTested];
[self.classBeingTested doSomethingThatwillCheckIfYourDelegateRespondsToYourOptionalMethod];
If you do not call markSelectorAsImplemented, then your classBeingTested will get NO for respondsToSleectorForThatMethod
I've put the code for it here. I'm using this to great effect. Thanks to jer on #iphonedev for setting me off on this path (overriding respondsToSelector was his idea, I was doing some crazy runtime method addition - this is much cleaner methinks).
here's the code
/**
* This class is specifically useful and intended for testing code paths that branch
* pending implementation of optional methods.
* OCMock does not support mocking of protocols with unimplemented optional methods.
* Further compounding the issue is the fact that OCMock does not allow mocking of
* respondsToSelector (in fact, it does but the behaviour is undefined),
* As such this class can be extending to implement a given protocol, the methods can be mocked/expected
* as normal, but in addition we can tell the class to report it conforms to a protocol method or not.
*
*/
#interface GCOCMockOptionalMethodSupportingObject : NSObject
- (void)markSelectorAsImplemented:(SEL)aSelector;
- (void)unmarkSelectorAsImplemented:(SEL)aSelector;
#end
#import "GCOCMockOptionalMethodSupportingObject.h"
#interface GCOCMockOptionalMethodSupportingObject ()
#property(nonatomic, strong) NSMutableArray *implementedSelectors;
#end
#implementation GCOCMockOptionalMethodSupportingObject {
}
//////////////////////////////////////////////////////////////
#pragma mark init
//////////////////////////////////////////////////////////////
- (id)init {
self = [super init];
if (self) {
self.implementedSelectors = [NSMutableArray array];
}
return self;
}
//////////////////////////////////////////////////////////////
#pragma mark public api
//////////////////////////////////////////////////////////////
- (void)markSelectorAsImplemented:(SEL)aSelector {
if (![self isImplemented:aSelector]) {
[self.implementedSelectors addObject:NSStringFromSelector(aSelector)];
}
}
- (void)unmarkSelectorAsImplemented:(SEL)aSelector {
for (NSString *selectorValue in [self.implementedSelectors mutableCopy]) {
SEL storedSelector = NSSelectorFromString(selectorValue);
if (sel_isEqual(aSelector, storedSelector)) {
[self.implementedSelectors removeObject:selectorValue];
break;
}
}
}
//////////////////////////////////////////////////////////////
#pragma mark private impl
//////////////////////////////////////////////////////////////
- (BOOL)isImplemented:(SEL)aSelector {
for (NSString *selectorValue in self.implementedSelectors) {
SEL storedSelector = NSSelectorFromString(selectorValue);
if (sel_isEqual(aSelector, storedSelector)) {
return YES;
}
}
return NO;
}
//////////////////////////////////////////////////////////////
#pragma mark overridden
//////////////////////////////////////////////////////////////
- (BOOL)respondsToSelector:(SEL)aSelector {
if ([self isImplemented:aSelector]) {
return YES;
} else {
return [super respondsToSelector:aSelector];
}
}
#end

The easiest thing to do is to create a class containing the selectors you do want implemented. There doesn't need to be any implementation. Then you create a class mock of that class instead of a protocol mock and use it just the same way.
For example:
#interface MyAwesomeImplementation : NSObject <MyAwesomeProtocol>
- (void)doThatRequiredThing;
#end
#implementation MyAwesomeImplementation
- (void)doThatRequiredThing {}
#end
id mock = OCMStrictClassMock([MyAwesomeImplementation class]);

Related

Is it possible to call the original delegate from a delegate?

Out of curiosity, is it possible to call the original delegate method implementation in a custom delegate implementation. like [super delegateMethod]; Or is that not possible. There are some scenarios where'd id like to add customizations to the behavior if certain conditions are met. Thank you in advance!
Yes, this can be achieved via a wrapper object which intercepts messages and forwards them to another delegate object. The following class intercepts calls to the scrollViewDidScroll: method before forwarding it (and any other delegate method invocations) to another UIScrollViewDelegate.
#import UIKit;
#interface ScrollHandler : NSObject <UIScrollViewDelegate>
- (instancetype)initWithScrollViewDelegate:(id<UIScrollViewDelegate>)delegate;
#end
#implementation ScrollHandler {
id<UIScrollViewDelegate> _scrollViewDelegate;
}
- (instancetype)initWithScrollViewDelegate:(id<UIScrollViewDelegate>)delegate {
self = [super init];
if (self) {
_scrollViewDelegate = delegate;
}
return self;
}
// Intercept specific method invocations:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
// Implement custom behavior here before forwarding the invocation to _scrollViewDelegate
[_scrollViewDelegate scrollViewDidScroll:scrollView];
}
// Forward unintercepted method invocations:
- (BOOL)respondsToSelector:(SEL)selector
{
// Ask _scrollViewDelegate if it responds to the selector (and ourself as well)
return [_scrollViewDelegate respondsToSelector:selector] || [super respondsToSelector:selector];
}
- (void)forwardInvocation:(NSInvocation *)invocation
{
// Forward the invocation to _scrollViewDelegate
[invocation invokeWithTarget:_scrollViewDelegate];
}
#end
Example use:
_scrollView = [[ScrollHandler alloc] init];
_scrollController = [[ScrollHandler alloc] initWithScrollViewDelegate:self];
_scrollView.delegate = _scrollController;

objective c message forwarding with forwardingTargetForSelector not always working

I have a view controller which defines a protocol which itself inherits another protocol.
I want any object that implements my protocol to also implement the inherited protocol.
I want to set my class to intercept some of the messages in the inherited protocol in order to configure some things internally but eventually would like to forward all of the messages to the delegate of my class
I could write a lot of boiler plate code to stub all of the protocol and intern call the delegate but I see that it breaks a lot of the time - any time the "super" protocol changes I need to restub this class once again.
I see that this is very predominant in custom UI controls. When reusing existing components - for instance tables or collection views you would like your data source to respond to all of the common protocols but some instances you need to configure the view according to the index or save a particular state.
I've tried using forwardingTargetForSelector in order to forward the messages I do not respond to , but it isn't always forwarding...
Here is a contrived code example:
Class A: (the top most protocol)
#
protocol classAProtocol <NSObject>
-(void)method1;
-(void)method2;
-(void)method3;
#end
My Class
#protocol MyClassProtocol <classAProtocol>
-(void)method4;
#end
#interface MyClass
#property (nonatomic,weak> id <MyClassProtocol> delegate;
#end
#interface MyClass (privateInterface)
#property (nonatomic,strong) ClassA *classAObject;
#end
#implementation MyClass
-(init)
{
self = [super init];
if (self)
{
_classAObject = [[ClassA alloc] init];
_classAObject.delegate = self; // want to answer some of the delegate methods but not all
}
}
-(void)method1
{
// do some internal configuration
// call my delegate with
[self.delegate method1];
}
-(id)forwardingTargetForSelector:(SEL)aSelector
{
if ([self respondsToSelector:aSelector])
{
return self;
}
if ([self.delegate respondsToSelector:aSelector])
{
return self.delegate;
}
return nil;
}
-(void)setDelegate:(id <MyClassProtocol>)delegate
{
self.delegate = delegate; // will forward some of the messages
}
#end
Returning self from forwardingTargetForSelector: makes no sense because it would never be called if self responded to the selector.
You need to implement these three methods:
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([self.delegate respondsToSelector:[anInvocation selector]])
[anInvocation invokeWithTarget:self.delegate];
else
[super forwardInvocation:anInvocation];
}
- (BOOL)respondsToSelector:(SEL)aSelector
{
return [super respondsToSelector:aSelector] || [self.delegate respondsToSelector:aSelector];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature *signature = [super methodSignatureForSelector:selector];
if (!signature) {
signature = [self.delegate methodSignatureForSelector:selector];
}
return signature;
}
You shouldn't ever return self; from forwardingTargetForSelector:. Your check should mean it never is but if you ever did return self it would cause an infinite loop.
You need to be sure that a super class isn't implementing the method as this will prevent forwardingTargetForSelector: from being called. Check if the method is actually called.
forwardingTargetForSelector: is also only called when a method is called on your controller that it doesn't respond to. In your example you aren't calling [self ...];, you're calling [self.delegate ...]; so forwardingTargetForSelector: will not be called.

Should I "Pull Up" Refactor

I have some very small classes that I feel should be "pulled up" but the methods are so small I'm not sure. For example, the only thing that's meaningfully different is the body of the buildFromJSON: selector.
I acknowledge that this is similar to:
Pull-up refactoring, Objective-C
but I feel my question is specific to refactoring very small classes/methods.
Also, not sure it relates to my particular code example, but I'm wondering if a child class says it conforms to a protocol, whether it's enough that it's parent actually supply the implementation of required selector(s)?
#implementation AsyncFoo
-(void)dealloc {
[clientDelegate release];
[super dealloc];
}
- (id)initWithDelegate: (id <ServiceClientProtocol>) delegate {
if((self = [super init])) {
clientDelegate = [delegate retain];
}
return self;
}
- (void)buildFromJSON:(NSString*)jsonResponseString {
[clientDelegate serviceComplete:[RestAdapter buildFooArray: jsonResponseString]];
}
#end
#implementation AsyncBar
-(void)dealloc {
[clientDelegate release];
[super dealloc];
}
- (id)initWithDelegate: (id <ServiceClientProtocol>) delegate {
if((self = [super init])) {
clientDelegate = [delegate retain];
}
return self;
}
- (void)buildFromJSON:(NSString*)jsonResponseString {
[clientDelegate serviceComplete:[RestAdapter buildBarArray:jsonResponseString]];
}
#end
Answers including code example would be great.
EDIT: Post accepted answer I'd like to add that since I was able to subclass, the derived classes did not need to declare that they conformed to protocol:
#interface Async : NSObject <ModelBuilderProtocol> {
id <ServiceClientProtocol> clientDelegate;
}
- (void)buildFromJSON:(NSString*)jsonResponseString;
#end
#interface AsyncArtistById : Async
#end
You don't normally retain your delegates as this can cause a retain cycle.
Knowing what I know from looking at your example I would probably implement like this:
The super class
// Async.h
#interface Async : NSObject
#property (nonatomic, assign) id<ServiceClientProtocol> delegate;
- (void)buildFromJSON:(NSString *)jsonResponseString;
#end
// Async.m
#implementation Async
#synthesize delegate = _delegate;
- (id)initWithDelegate:(id<ServiceClientProtocol>)delegate
{
self = [super init];
if(self) {
_delegate = delegate;
}
return self;
}
- (void)buildFromJSON:(NSString *)jsonResponseString
{
// This will ensure that we over ride this method in a sub class
[NSException raise:NSInternalInconsistencyException
format:#"You must override %# in a subclass", NSStringFromSelector(_cmd)];
}
#end
Concrete subclass AsyncFoo
// AsyncFoo.h
#interface AsyncFoo : Async
#end
// AsyncFoo.m
#implementation AsyncFoo
- (void)buildFromJSON:(NSString *)jsonResponseString
{
[self.delegate serviceComplete:[RestAdapter buildFooArray: jsonResponseString]];
}
#end
Concrete subclass AsyncBar
// AsyncBar.h
#interface AsyncBar : Async
#end
// AsyncBar.m
#implementation AsyncBar
- (void)buildFromJSON:(NSString *)jsonResponseString {
[self.delegate serviceComplete:[RestAdapter buildBarArray:jsonResponseString]];
}
#end

What is the "template method pattern" in cocoa with Object C ? ( Language comparison thinking )

Here is template method pattern , Java and C++ can implement it easily with virtual function. How about Object C to implement this pattern ? Any example in cocoa touch (iOS) ?
As jer has already pointed out, all Objective-C methods are essentially virtual. It is a feature of the language which does not quite mesh with other C-like languages. That being said, the basics of the template method pattern can still be achieved in Objective-C, by "manually" forcing subclasses to implement certain functions. For example (using the convention in your linked Wikipedia article):
#interface Game
{
int playersCount;
}
- (void)playOneGame:(int)numPlayers;
// "virtual" methods:
- (void)initializeGame;
- (void)makePlay:(int)player;
- (BOOL)endOfGame;
- (void)printWinner;
#end
#implementation Game
- (void)initializeGame { NSAssert(FALSE); }
- (void)makePlay:(int player) { NSAssert(FALSE); }
- (BOOL)endOfGame { NSAssert(FALSE); return 0; }
- (void)printWinner { NSAssert(FALSE); }
- (void)playOneGame:(int)numPlayers
{
//..
}
#end
The above code forces subclasses of Game to override the "virtual" methods by throwing an exception the moment one of the base class implementations is called. In effect, this moves the test from the compiler stage (as it would be in C++ or Java) and into the runtime stage (where similar things are often done in Objective-C).
If you really want to enforce the rule that subclasses are not allowed to override the playOneGame: method, you can attempt(*) to verify the correct implementation from within the init method:
#implementation Game
...
- (void)init
{
if ((self = [super init]) == nil) { return nil; }
IMP my_imp = [Game instanceMethodForSelector:#selector(playOneGame:)];
IMP imp = [[self class] instanceMethodForSelector:#selector(playOneGame:)];
NSAssert(imp == my_imp);
return self;
}
...
#end
(*) Note that this code does not result in a 100% rock-solid defense against subclasses which re-implement playOneGame:, since the very nature of Objective-C would allow the subclass to override instanceMethodForSelector: in order to produce the correct result.
In Objective-C all methods are akin to C++ virtual methods.
In Objective-C Template Method Pattern is Used When you have a Skeleton of an Algorithm but it can be Implemented in different ways. Template method defines the steps to execute an algorithm and it can provide default implementation that might be common for all or some of the subclasses.
Let's take an example but First Look at the Picture
#interface Worker : NSObject
- (void) doDailyRoutine;
- (void) doWork; // Abstract
- (void) comeBackHome;
- (void) getsomeSleep;
#end
#implementation Worker
- (void) doDailyRoutine {
[self doWork];
[self comeBackHome];
[self getsomeSleep];
}
- (void) doWork { [self doesNotRecognizeSelector:_cmd]; }
- (void) comeBackHome { [self doesNotRecognizeSelector:_cmd]; }
- (void) getsomeSleep { [self doesNotRecognizeSelector:_cmd]; }
// [self doesNotRecognizeSelector:_cmd] it will force to call the subclass Implementation
#end
#interface Plumber : Worker
#end
#implementation Plumber
- (void) doWork { NSLog(#“Plumber Work"); }
#end
#interface Electrician : Worker
#end
#implementation Electrician
- (void) doWork { NSLog(#“Electrician Work"); }
#end
#interface Cleaner : Worker
#end
#implementation Cleaner
- (void) doWork { NSLog(#“Cleaner Work"); }
#end
In this example dowork() is an Abstract function which should be implemented by all the subclasses and this pattern is largely used in Cocoa Frameworks.
Hope it will help you to Understand the "Template Method Pattern".

How to create a strategy pattern in Objective-C?

I need to develop a strategy pattern where i have a main class with other three classes where i need to refer to the objects of the other three classes using the main class object.To solve this is the strategy pattern will help me? If so please do give me the syntax in Objective-C?
You'll want to look at Objective-C's protocol mechanism. Here's a simple protocol with a single required method:
#protocol Strategy <NSObject>
#required
- (void) execute;
#end
Then you declare a class that fulfills that protocol:
#interface ConcreteStrategyA : NSObject <Strategy>
{
// ivars for A
}
#end
The implementation must provide the -execute method (since it was declared as #required):
#implementation ConcreteStrategyA
- (void) execute
{
NSLog(#"Called ConcreteStrategyA execute method");
}
#end
You can make a similar ConcreteStrategyB class, but I'm not going to show it here.
Finally, make a context class with a property maintaining the current strategy.
#interface Context : NSObject
{
id<Strategy> strategy;
}
#property (assign) id<Strategy> strategy;
- (void) execute;
#end
Here is the implementation. The method that delegates to the strategy's -execute method just happens to be called -execute as well, but it doesn't have to be.
#implementation Context
#synthesize strategy;
- (void) execute
{
[strategy execute];
}
#end
Now I'll make a few instances and put them to use:
ConcreteStrategyA * concreteStrategyA = [[[ConcreteStrategyA alloc] init] autorelease];
ConcreteStrategyB * concreteStrategyB = [[[ConcreteStrategyB alloc] init] autorelease];
Context * context = [[[Context alloc] init] autorelease];
[context setStrategy:concreteStrategyA];
[context execute];
[context setStrategy:concreteStrategyB];
[context execute];
The console output shows that the strategy was successfully changed:
2010-02-09 19:32:56.582 Strategy[375:a0f] Called ConcreteStrategyA execute method
2010-02-09 19:32:56.584 Strategy[375:a0f] Called ConcreteStrategyB execute method
Note that if the protocol does not specify #required, the method is optional. In this case, the context needs to check whether the strategy implements the method:
- (void) execute
{
if ([strategy respondsToSelector:#selector(execute)])
[strategy execute];
}
This is a common Cocoa pattern called delegation. For more information on delegation and other design patterns in Cocoa, see this.
Here's a bit more of a concrete example. You can put each item in a separate file. I've put it all in one file for ease of understanding.
// main.m
// StrategyWikipediaExample
//
// Created by steve on 2014-07-08.
// Copyright (c) 2014 steve. All rights reserved.
//
#import <Foundation/Foundation.h>
/**
Equivalent to Java Interface
All concrete Strategies conform to this protocol
*/
#protocol MathOperationsStrategy<NSObject>
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second;
#end
/**
Concrete Strategies.
Java would say they "Extend" the interface.
*/
#interface AddStrategy : NSObject<MathOperationsStrategy>
#end
#implementation AddStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
NSInteger result = first + second;
NSLog(#"Adding firstNumber: %ld with secondNumber: %ld yields : %ld", first, second, result);
}
#end
#interface SubtractStrategy : NSObject<MathOperationsStrategy>
#end
#implementation SubtractStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
NSInteger result = first - second;
NSLog(#"Subtracting firstNumer: %ld with secondNumber: %ld yields: %ld", first, second, result);
}
#end
#interface MultiplyStrategy : NSObject<MathOperationsStrategy>
#end
#implementation MultiplyStrategy
- (void)performAlgorithmWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
NSInteger result = first * second;
NSLog(#"Multiplying firstNumber: %ld with secondNumber: %ld yields: %ld", first, second, result);
}
#end
#interface Context : NSObject
#property (weak, nonatomic)id<MathOperationsStrategy>strategy; // reference to concrete strategy via protocol
- (id)initWithMathOperationStrategy:(id<MathOperationsStrategy>)strategy; // setter
- (void)executeWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second;
#end
#implementation Context
- (id)initWithMathOperationStrategy:(id<MathOperationsStrategy>)strategy
{
if (self = [super init]) {
_strategy = strategy;
}
return self;
}
- (void)executeWithFirstNumber:(NSInteger)first secondNumber:(NSInteger)second
{
[self.strategy performAlgorithmWithFirstNumber:first secondNumber:second];
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
id<MathOperationsStrategy>addStrategy = [AddStrategy new];
Context *contextWithAdd = [[Context alloc] initWithMathOperationStrategy:addStrategy];
[contextWithAdd executeWithFirstNumber:10 secondNumber:10];
}
return 0;
}