編輯:這是由我的其他鏈接標誌設置中的拼寫錯誤造成的。有關更多信息,請參閱my answer below。OCMock:爲什麼我在嘗試調用UIWebView模擬時遇到無法識別的選擇器異常?
我試圖嘲笑一個UIWebView,以便我可以驗證它的方法在iOS視圖控制器的測試期間被調用。我正在使用一個由SVN修訂版70(這個問題最近的時間)構建的OCMock靜態庫,以及來自SVN的410版Google Toolbox for Mac(GTM)單元測試框架。當視圖控制器嘗試調用預期的方法時,出現以下錯誤。
Test Case '-[FirstLookViewControllerTests testViewDidLoad]' started.
2010-11-11 07:32:02.272 Unit Test[38367:903] -[NSInvocation getArgumentAtIndexAsObject:]: unrecognized selector sent to instance 0x6869ea0
2010-11-11 07:32:02.277 Unit Test[38367:903] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSInvocation getArgumentAtIndexAsObject:]: unrecognized selector sent to instance 0x6869ea0'
*** Call stack at first throw:
(
0 CoreFoundation 0x010cebe9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x012235c2 objc_exception_throw + 47
2 CoreFoundation 0x010d06fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x01040366 ___forwarding___ + 966
4 CoreFoundation 0x0103ff22 _CF_forwarding_prep_0 + 50
5 Unit Test 0x0000b29f -[OCMockRecorder matchesInvocation:] + 216
6 Unit Test 0x0000c1c1 -[OCMockObject handleInvocation:] + 111
7 Unit Test 0x0000c12a -[OCMockObject forwardInvocation:] + 43
8 CoreFoundation 0x01040404 ___forwarding___ + 1124
9 CoreFoundation 0x0103ff22 _CF_forwarding_prep_0 + 50
10 Unit Test 0x0000272a -[MyViewController viewDidLoad] + 100
11 Unit Test 0x0000926c -[MyViewControllerTests testViewDidLoad] + 243
12 Unit Test 0x0000537f -[SenTestCase invokeTest] + 163
13 Unit Test 0x000058a4 -[GTMTestCase invokeTest] + 146
14 Unit Test 0x0000501c -[SenTestCase performTest] + 37
15 Unit Test 0x000040c9 -[GTMIPhoneUnitTestDelegate runTests] + 1413
16 Unit Test 0x00003a87 -[GTMIPhoneUnitTestDelegate applicationDidFinishLaunching:] + 197
17 UIKit 0x00309253 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1252
18 UIKit 0x0030b55e -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 439
19 UIKit 0x0030aef0 -[UIApplication _run] + 452
20 UIKit 0x0031742e UIApplicationMain + 1160
21 Unit Test 0x0000468c main + 104
22 Unit Test 0x000026bd start + 53
23 ??? 0x00000002 0x0 + 2
)
terminate called after throwing an instance of 'NSException'
/Users/gjritter/src/google-toolbox-for-mac-read-only/UnitTesting/RunIPhoneUnitTest.sh: line 151: 38367 Abort trap "$TARGET_BUILD_DIR/$EXECUTABLE_PATH" -RegisterForSystemEvents
我的測試代碼:
- (void)testViewDidLoad {
MyViewController *viewController = [[MyViewController alloc] init];
id mockWebView = [OCMockObject mockForClass:[UIWebView class]];
[[mockWebView expect] setDelegate:viewController];
viewController.webView = mockWebView;
[viewController viewDidLoad];
[mockWebView verify];
[mockWebView release];
}
我的視圖控制器代碼:
- (void)viewDidLoad {
[super viewDidLoad];
webView.delegate = self;
}
我也覺得,如果我代替測試將成功運行:
- (void)testViewDidLoad {
MyViewController *viewController = [[MyViewController alloc] init];
id mockWebView = [OCMockObject partialMockForObject:[[UIWebView alloc] init]];
//[[mockWebView expect] setDelegate:viewController];
viewController.webView = mockWebView;
[viewController viewDidLoad];
[mockWebView verify];
[mockWebView release];
}
但是,只要我加入d被註釋掉的期望,使用部分模擬時返回的錯誤。
我有其他測試成功地在同一個項目中使用模擬。
任何想法?嘲笑OCMock支持的UIKit對象嗎?
編輯:基於下面的答案的建議,我嘗試了下面的測試,但我得到了同樣的錯誤:
- (void)testViewDidLoadLoadsWebView {
MyViewController *viewController = [[MyViewController alloc] init];
UIWebView *webView = [[UIWebView alloc] init];
// This test fails in the same fashion with or without the next line commented
//viewController.view;
id mockWebView = [OCMockObject partialMockForObject:webView];
// When I comment out the following line, the test passes
[[mockWebView expect] loadRequest:[OCMArg any]];
viewController.webView = mockWebView;
[viewController viewDidLoad];
[mockWebView verify];
[mockWebView release];
}
對不起,不接受或評論你的答案。我在一個漫長的週末後回到工作崗位,今天晚些時候就可以測試。 – Greg 2010-11-15 18:11:51
你說得對,我給出的示例測試不需要模擬。我發佈了一個新的樣本測試,確實需要模擬。我嘗試使用viewController.view來強制視圖加載,但是當我這樣做時仍然會出現相同的錯誤。 – Greg 2010-11-16 02:14:10
對不起,浪費你的時間 - 我的問題是我的其他鏈接標誌中的拼寫錯誤。我對你的回答提出了一個有用的觀點,即我的問題中的原始測試甚至不需要使用模擬。最好只在需要的地方使用mock。 – Greg 2010-11-16 03:15:23