MeloS
MeloS

Reputation: 7938

OCMockito: RACObserve a mocked object always fail

code like this:

@implementation MyClass

- (void)func
{
//MyOtherClassObject is an object passed in when initialising MyClass
    NSArray *signals = @[[RACObserve(MyOtherClassObject, prop) subscribeNext:^{{}]];
}

@end

@implementation MyTest

- (void)testSomething
{
    MyOtherClass *mock = mock([MyOtherClass class]);
    MyClass *myObject = [[MyClass alloc] initWithOtherObject:mock]
    [myObject func];  //this won't work since RACObserve will return nil instead of a valid signal
}

@end

So, is there any way I can get a mocked object RACObserved like normal object?

Upvotes: 1

Views: 194

Answers (1)

Michał Ciuba
Michał Ciuba

Reputation: 7944

This is because OCMockito (and OCMock as well) breaks Key-Value Observing, that is, you won't get any KVO "callbacks" from the mocked objects. And RACObserve uses KVO under the hood. There are many possible workarounds:

  1. As described in OCMockito docs:

How do you stub a property so that KVO works? Use stubProperty(instance, property, value). For example:

stubProperty(mockEmployee, firstName, @"fake-firstname");

I haven't used OCMockito so I can't tell whether this will really work with RAC.

  1. Use a real object instead of a mock. It will work for some cases (when the object is really simple and you just need to change a property). Of course it shouldn't be used when it will break isolation of the unit test (for example, by sending a network request or accessing a database / file system).

  2. Extract the signal returned by RACObserve to a property and stub. Instead of

NSArray *signals = @[[RACObserve(MyOtherClassObject, prop) subscribeNext:^{{}]];

do:

NSArray *signals = MyOtherClassObject.prop

where MyOtherClassObject.prop will return RACObserve(self, prop). Then you can easily stub MyOtherClassObject.prop and return any signal, for example [RACSignal return:] for getting a single value synchronously.

Upvotes: 1

Related Questions