我有一个错误,似乎与OCMockObject PartialMock有关。当对一个对象进行嘲讽并存根方法时,我得到了这个未识别的选择器错误,我很确定这是一个顺序或铸造问题。
STV_StreamServer *server = [NSEntityDescription insertNewObjectForEntityForName:@"STV_StreamServer"inManagedObjectContext:context];
id mockServer = [OCMockObject partialMockForObject:server];
[[[mockServer stub] andReturnValue:@YES] localURLPresent];
[[[mockServer stub] andReturnValue:@NO] remoteURLPresent];
id mockSUT = [OCMockObject partialMockForObject:sut];
[[[mockSUT stub] andReturnValue:@YES] canLiveStream:nil];
sut.streamServer = mockServer;
NSError *err = [mockSUT checkStreamingPlayabilityForUser:[self getUser:NO]];
XCTAssertNil(err, @"An error occured when basic user tried local playback");
sut是一个STV_MediaServer。我得到的错误是 [STV_MediaServer-0xb39aba0-407898154.181220 setStreamServer:]: unrecognized selector sent to instance 0xb39aba0
. 因此,首先我看到对象类型似乎是错误的,因为它现在包括看起来像一个内存位置。当我模拟我的sut时就会出现这种情况。我确信这是一个顺序问题。我在网上查了几个小时。
我没有重现你的问题,但我认为在托管对象中不可能存根属性(用@dynamic声明的CoreData)。
对于你所展示的这种情况,你可以简单地将属性设置为你想要的值--这里不需要存根。
你得到这个错误是因为你在mockSUT上调用了这个方法。由于CoreData生成属性访问器的方式,OCMock无法将它们的实现复制到部分mock中,因此它们无法被ObjC运行时找到。
当checkStreamingPlayabilityForUser最终调用self.streamServer时,self实际上是mockSUT,无法找到方法'streamServer'。
如果你只是简单地按照你需要的方式配置管理对象来进行这个特定的测试,这将会很好地工作。
FWIW你永远不应该尝试模拟NSManagedObject的实例,执行这些类型的测试的首选方法是简单地在单元测试中创建符合你需要的配置的测试对象。
使用核心数据进行数据驱动测试。
如果你创建一个SenTestCase或XCTestCase的子类,可以为你管理CoreData位,这将会有所帮助。这个测试用例子类应该提供一个NSManagedObjectContext的实例供你的测试使用。
一个实际的测试可能看起来像这样。
@implementation PeopleViewControllerTest
- (void)testSomething {
NSMutableArray *people = [NSMutableArray new];
[self.managedObjectContext performBlockAndWait:^{
for (int i=0; i < 100; i++) {
Person *p = [NSEntityDescription insertNewObjectForEntityForName:@"Person"
inManagedObjectContext:self.managedObjectContext];
p.firstName = [NSString stringWithFormat:@"First%d", i];
[people addObject:p];
}
}];
//return the people
PeopleViewController *pvc = ...;
id mockPVC = [OCMockObject partialMockForObject:pvc];
[[[mockPVC stub] andReturn:people] fetchedPeople];
//make sure the view controller behaves properly with these 100 people
}
@end
所以我们不需要创建100个NSManagedObject的模拟实例 我们只需要创建100个实际的对象。
我们并不是要测试CoreData,只是测试建立在NSManagedObjects之上的逻辑。因此,创建具体的NSManagedObject实例是可以的,但它们应该被配置为行使你的应用程序的逻辑。
即,如果你想检查电子邮件地址验证,你可能会有。
p.emailAddress = @"notvalid";
/后期用一些模拟对象[[[partialMock expect] andReturn:p] person]。