This is an example unit test using Specta, Expecta and OCMock.
Another example - WordPress iOS app unit test.
#import "Specta.h"
#define EXP_SHORTHAND
#import "Expecta.h"
#import <OCMock/OCMock.h>
#import "RoomListViewModel.h"
#import <EXTScope.h>
SpecBegin(RoomListViewModel)
describe(@"RoomListViewModel", ^{
__block RoomListViewModel *viewModel;
__block id home;
__block id room;
beforeAll(^{
});
beforeEach(^{
home = OCMClassMock([HMHome class]);
room = OCMClassMock([HMRoom class]);
viewModel = [[RoomListViewModel alloc] initWithHome:home];
});
it(@"add room with name", ^{
OCMStub([home addRoomWithName:OCMOCK_ANY completionHandler:OCMOCK_ANY]).andDo(^(NSInvocation *invocation) {
void(^ __unsafe_unretained completionHandler)(HMRoom *room, NSError *error);
[invocation getArgument:&completionHandler atIndex:3];
completionHandler(room, nil);
});
waitUntil(^(DoneCallback done) {
@weakify(viewModel);
[viewModel addRoomWithName:@"test" completionHandler:^(NSError *error) {
@strongify(viewModel);
expect(...);
done();
}];
});
});
afterEach(^{
viewModel = nil;
});
afterAll(^{
});
});
SpecEnd
void(^ __unsafe_unretained completionHandler)(HMRoom *room, NSError *error);
Why declare our block __unsafe_unretained?
See http://stackoverflow.com/a/13831074/1060971, Carl Lindberg’s comment.
[invocation getArgument:&completionHandler atIndex:3];
In NSInvocation, argument index 0 is self , index 1 is cmd.
First argument of addRoomWithName is at index 2, completion block argument is at index 3.
So, assign our mock block at index 3.