Open s-hocking opened 4 years ago
I'm afraid you're not using the correct methods for ObjC mocking. Please post the whole test, so I can verify how you create mocks, stub them, and verify them.
Thanks for the response. Here's a brief test class that illustrates my problem:
class CuckooBluetoothDemo: XCTestCase {
var mockCentral: CBCentralManager!
override func setUpWithError() throws {
mockCentral = objcStub(for: CBCentralManager.self) { stubber, mock in
// Neither of these stubs compile:
stubber.when(mock.delegate.set).then { args in // Value of type 'CBCentralManagerDelegate?' has no member 'set'
}
stubber.when(mock.setDelegate).then { args in // Value of type 'CBCentralManager' has no member 'setDelegate'
}
}
}
func testSettingDelegate() throws {
// This line triggers an error because the delegate is not stubbed:
// caught "NSInternalInconsistencyException", "OCMockObject(CBCentralManager): unexpected method invoked: setDelegate:-[CuckooBluetoothDemo testSettingDelegate] "
mockCentral.delegate = self
}
}
extension CuckooBluetoothDemo: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
// This method is just here to satisfy the compiler
}
}
Hey, I just played around a bit with this. We were missing a NSObjectProtocol
support.
Please try branch fix/objc-nsobjectprotocol
, no need to rebuild/redownload the generator, this change affects only Cuckoo
internals, so just install pods again after changing the Podfile
.
Thank you so much for bringing this to light, if you come up with any other shortcomings, let us know and we'll hopefully find a way to fix them.
Oh and in ObjC mocking, you needn't specify anything like .set
, just call it like you would, it's an autoclosure to make sure that OCMock
can do its thing.
Thanks for looking in to this! I've tried out your bug fix branch, which makes it possible to mock out the delegate
return value 👍
I've still got an issue though when the delegate
property is set. The test fails because setDelegate:
is not mocked. How can I mock this method?
class CuckooBluetoothDemo: XCTestCase {
var mockCentral: CBCentralManager!
override func setUpWithError() throws {
mockCentral = objcStub(for: CBCentralManager.self) { stubber, mock in
stubber.when(mock.delegate).thenReturn(self) // this now works with the updated branch!
}
}
func testSettingDelegate() throws {
// This line still fails the test because setDelegate: is not stubbed, with error:
// caught "NSInternalInconsistencyException", "OCMockObject(CBCentralManager): unexpected method invoked: setDelegate:-[CuckooBluetoothDemo testSettingDelegate] "
mockCentral.delegate = self
}
}
extension CuckooBluetoothDemo: CBCentralManagerDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
// This method is just here to satisfy the compiler
}
}
Thanks for the feedback, I'll take a look at it, hopefully it's nothing too major.
Hi! I just ran into this myself too, how do I need to change Podfile to add fix/objc-nsobjectprotocol branch?
Like this?
pod 'Cuckoo', :git => 'https://github.com/Brightify/Cuckoo.git', :branch => 'fix/objc-nsobjectprotocol'
I've changed the Podfile, still getting the same error but I am not sure it is related with the poster´s issue
caught "NSInternalInconsistencyException", "OCMockObject(MiBancoAPIClient): unexpected method invoked: expireSessionWithCompletion:<__NSMallocBlock__: 0x600000054240>
stubbed: hostAvailable
stubbed: isSessionStillValid"
(
0 CoreFoundation 0x00007fff23e3cf0e __exceptionPreprocess + 350
1 libobjc.A.dylib 0x00007fff50ba89b2 objc_exception_throw + 48
2 CoreFoundation 0x00007fff23e3cd4c +[NSException raise:format:] + 188
3 OCMock 0x0000000109ab76ce -[OCMockObject handleUnRecordedInvocation:] + 190
4 OCMock 0x0000000109ab6a2d -[OCMockObject forwardInvocation:] + 93
5 CoreFoundation 0x00007fff23e416b6 ___forwarding___ + 838
6 CoreFoundation 0x00007fff23e43bf8 _CF_forwarding_prep_0 + 120
7 CoreFoundation 0x00007fff23e43e8c __invoking___ + 140
8 CoreFoundation 0x00007fff23e41071 -[NSInvocation invoke] + 321
9 CoreFoundation 0x00007fff23e41344 -[NSInvocation invokeWithTarget:] + 68
10 Cuckoo 0x00000001099e191a -[CuckooMockObject forwardInvocation:] + 586
11 CoreFoundation 0x00007fff23e416b6 ___forwarding___ + 838
12 CoreFoundation 0x00007fff23e43bf8 _CF_forwarding_prep_0 + 120
13 MiBancoSwiftTests 0x00000001093affa6 $s17MiBancoSwiftTests06CuckooD0C7testApiyyF + 246
14 MiBancoSwiftTests 0x00000001093b035b $s17MiBancoSwiftTests06CuckooD0C7testApiyyFTo + 43
15 CoreFoundation 0x00007fff23e43e8c __invoking___ + 140
16 CoreFoundation 0x00007fff23e41071 -[NSInvocation invoke] + 321
17 XCTest 0x0000000109082037 __24-[XCTestCase invokeTest]_block_invoke_2 + 52
18 XCTest 0x0000000109081fe3 __24-[XCTestCase invokeTest]_block_invoke.206 + 320
19 XCTest 0x00000001090dcdc2 +[XCTestCase(Failures) performFailableBlock:testCase:testCaseRun:shouldInterruptTest:] + 69
20 XCTest 0x00000001090dccd4 -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 115
21 XCTest 0x00000001090819f6 -[XCTestCase invokeTest] + 1183
22 XCTest 0x0000000109083329 __26-[XCTestCase performTest:]_block_invoke_2 + 43
23 XCTest 0x00000001090dcdc2 +[XCTestCase(Failures) performFailableBlock:testCase:testCaseRun:shouldInterruptTest:] + 69
24 XCTest 0x00000001090dccd4 -[XCTestCase(Failures) _performTurningExceptionsIntoFailuresInterruptAfterHandling:block:] + 115
25 XCTest 0x0000000109083260 __26-[XCTestCase performTest:]_block_invoke.359 + 86
26 XCTest 0x00000001090efa0d +[XCTContext runInContextForTestCase:block:] + 211
27 XCTest 0x0000000109082b14 -[XCTestCase performTest:] + 566
28 XCTest 0x00000001090c938e -[XCTest runTest] + 57
29 XCTest 0x000000010907cd50 __27-[XCTestSuite performTest:]_block_invoke + 354
30 XCTest 0x000000010907c4a2 __59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke + 24
31 XCTest 0x00000001090efa0d +[XCTContext runInContextForTestCase:block:] + 211
32 XCTest 0x000000010907c459 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 148
33 XCTest 0x000000010907c7be -[XCTestSuite performTest:] + 348
34 XCTest 0x00000001090c938e -[XCTest runTest] + 57
35 XCTest 0x000000010907cd50 __27-[XCTestSuite performTest:]_block_invoke + 354
36 XCTest 0x000000010907c4a2 __59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke + 24
37 XCTest 0x00000001090efa0d +[XCTContext runInContextForTestCase:block:] + 211
38 XCTest 0x000000010907c459 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 148
39 XCTest 0x000000010907c7be -[XCTestSuite performTest:] + 348
40 XCTest 0x00000001090c938e -[XCTest runTest] + 57
41 XCTest 0x000000010907cd50 __27-[XCTestSuite performTest:]_block_invoke + 354
42 XCTest 0x000000010907c4a2 __59-[XCTestSuite _performProtectedSectionForTest:testSection:]_block_invoke + 24
43 XCTest 0x00000001090efa0d +[XCTContext runInContextForTestCase:block:] + 211
44 XCTest 0x000000010907c459 -[XCTestSuite _performProtectedSectionForTest:testSection:] + 148
45 XCTest 0x000000010907c7be -[XCTestSuite performTest:] + 348
46 XCTest 0x00000001090c938e -[XCTest runTest] + 57
47 XCTest 0x00000001090fef14 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke + 171
48 XCTest 0x00000001090ff001 __44-[XCTTestRunSession runTestsAndReturnError:]_block_invoke.100 + 96
49 XCTest 0x0000000109097746 -[XCTestObservationCenter _observeTestExecutionForBlock:] + 682
50 XCTest 0x00000001090fec9f -[XCTTestRunSession runTestsAndReturnError:] + 615
51 XCTest 0x0000000109060744 -[XCTestDriver runTestsAndReturnError:] + 456
52 XCTest 0x00000001090eb64c _XCTestMain + 2496
53 libXCTestBundleInject.dylib 0x0000000107c4cbfa __copy_helper_block_e8_32s + 0
54 CoreFoundation 0x00007fff23da0b5c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
55 CoreFoundation 0x00007fff23da0253 __CFRunLoopDoBlocks + 195
56 CoreFoundation 0x00007fff23d9b043 __CFRunLoopRun + 995
57 CoreFoundation 0x00007fff23d9a944 CFRunLoopRunSpecific + 404
58 GraphicsServices 0x00007fff38ba6c1a GSEventRunModal + 139
59 UIKitCore 0x00007fff48c8b9ec UIApplicationMain + 1605
60 MiBanco Dev 0x0000000106926bc0 main + 112
61 libdyld.dylib 0x00007fff51a231fd start + 1
62 ??? 0x0000000000000005 0x0 + 5
)
Hey, @quetool. Your issue is not quite relevant to @s-hocking's. Your mockApiClient
doesn't stub the expireSession
method, so OCMock tells you that in the error message.
As for calling the setter for resolving @s-hocking, I'm pretty stumped without the necessary experience in ObjC to include this functionality at the moment. I'll leave the issue open and see if either I or @TadeasKriz gets some bright idea.
I am having almost the same issue as @s-hocking. Using objcStub()
, the class I'm testing sets delegate
on the mock, test fails.
Looking through the OCMock code and documentation, it seems like maybe the mock that objcStub()
creates is a strict mock and will always fail if an unstubbed method is invoked (setDelegate
in this case). If Cuckoo/OCMock exposes a way to make "nice" mocks, @s-hocking and I might be unstuck.
OCMock's method for making "nice" mocks: https://github.com/erikdoe/ocmock/blob/6358799e04cb93d8f126f1ea6a67e2e351b169f1/Examples/iOS5Example/usr/include/OCMock/OCMockObject.h#L22
Hey @jandrewmoore, that might work, and even if it doesn't for some reason, it's still a good feature to have. Thanks for doing the research. 🙂
Hi there. I'm currently trying to mock out
CBCentralManager
using the experimental ObjC stubbing feature. I've run into an issue with thedelegate
property on this class... If I don't stub thedelegate
property, OCMock fails my test when my code accesses thedelegate
property, with "unexpected method invoked":caught "NSInternalInconsistencyException", "OCMockObject(CBCentralManager): unexpected method invoked: setDelegate:<MySDKProject.BLECentral: 0x7fa1964178a0>
So I then try to stub the
delegate
property, but nothing seems to work.stubber.when(mock.delegate.set).then...
complains with "Value of type 'CBCentralManagerDelegate?' has no member 'set'"stubber.when(mock.setDelegate(any()))
complains thatValue of type 'CBCentralManager' has no member 'setDelegate'
What am I doing wrong?
Edit: for anyone else trying to mock CoreBluetooth classes, this project from Nordic Semiconductor looks pretty good!