OCMock 和 AVCaptureDeviceInput

OCMock and AVCaptureDeviceInput

我正在将我们的测试套件从 OCMock 2 更新到 OCMock 3,并且 运行 遇到了一些问题。 问题之一是我们正在尝试模拟 AVCaptureDeviceInput。

对于其中一个测试,当在 AVCaptureDeviceInput 上调用 class 方法时,我们希望 return 模拟实例 AVCaptureDeviceInput。

在我们的设置方法中:

 self.mockAVCaptureDeviceInputClass = [OCMockObject mockForClass:[AVCaptureDeviceInput class]];

在我们的测试中:

    id deviceInput = [OCMockObject mockForClass: [AVCaptureDeviceInput class]];
    [[[[self.mockAVCaptureDeviceInputClass stub] classMethod] andReturn:deviceInput]
     deviceInputWithDevice:mockDevice error:((NSError __autoreleasing **)[OCMArg setTo:nil])];

问题似乎是 deviceInput 覆盖了 self.mockAVCaptureDeviceInputClass,因此当 classMethod 被存根时,它不会做任何事情。

我尝试解决这个问题的另一种方法是为 AVCaptureDeviceInput 的实例创建一个模拟,但它只是挂起:

[OCMockObject partialMockForObject: [AVCaptureDeviceInput new]];

具有以下堆栈跟踪:

    0x000000010938a219 in _object_set_associative_reference ()
    0x0000000108aed5c3 in OCMSetAssociatedMockForClass at /Users/otusweb/Desktop/dfsa/Pods/OCMock/Source/OCMock/OCMFunctions.m:226
    0x00000001144ecce2 in -[OCClassMockObject prepareClassForClassMethodMocking] at /Users/otusweb/Desktop/dfsa/Pods/OCMock/Source/OCMock/OCClassMockObject.m:89
    0x00000001144ec934 in -[OCClassMockObject initWithClass:] at /Users/otusweb/Desktop/dfsa/Pods/OCMock/Source/OCMock/OCClassMockObject.m:31
    0x00000001144f47f6 in -[OCPartialMockObject initWithObject:] at /Users/otusweb/Desktop/dfsa/Pods/OCMock/Source/OCMock/OCPartialMockObject.m:33
    0x00000001144f1cdd in +[OCMockObject partialMockForObject:] at /Users/otusweb/Desktop/dfsa/Pods/OCMock/Source/OCMock/OCMockObject.m:58
    0x00000001144e9abe in -[dfsaTests testExample] at /Users/otusweb/Desktop/dfsa/dfsaTests/dfsaTests.m:33

您 运行 遇到了一个常见问题:对于给定的 class,只有一个模拟对象可以模拟 class 方法。这记录在限制部分 (http://ocmock.org/reference/#limitations) 中。当前创建的最后一个模拟 "wins"。

您的情况是您在设置方法中设置了第一个模拟 (self.mockAVCaptureDeviceInputClass),然后您在测试中为相同的 class 创建了第二个模拟 (deviceInput).此时只有后者可以在 AVCaptureDeviceInput.

上存根 class 方法

这个问题越来越普遍,我决定向 OCMock 添加警告。我正在考虑模拟对象在它因 class 方法存根而被停用时具有活动存根的情况下打印警告。 FWIW,正在进行一些调查,看看是否有可能在同一个 class (https://github.com/erikdoe/ocmock/issues/173) 上有多个模拟对象 mock class 方法,但这并非微不足道。