2013-01-19 49 views
3

所以我有一个类为我编写了一些测试用例。这个类有两种方法:模拟在测试用例中调用其方法的类

- (void)showNextNewsItem { 
    self.xmlUrl = self.nextNewsUrl; 
    [self loadWebViewContent]; 
} 

- (void)showPreviousNewsItem { 
    self.xmlUrl = self.previousNewsUrl; 
    [self loadWebViewContent]; 
} 

可重构,这是相当原始的,但尽管如此,我只想做一个和前一个负载以前知道下一步负载。所以我用OCMock实例为我的SUT类OCMockObject这样的:

- (void)testShowNextOrPreviousItemShouldReloadWebView { 

    id mockSut = [OCMockObject mockForClass:[NewsItemDetailsViewController class]]; 

    [[[mockSut expect] andReturn:@"http://www.someurl.com"] nextNewsUrl]; 
    [[mockSut expect] loadWebViewContent]; 

    [[[mockSut expect] andReturn:@"http://www.someurl.com"] previousNewsUrl]; 
    [[mockSut expect] loadWebViewContent]; 

    [mockSut showNextNewsItem]; 
    [mockSut showPreviousNewsItem]; 

    [mockSut verify]; 
} 

问题出在两行实际上是调用该做些什么来进行验证的方法。 OCMock现在告诉我,调用showNextNewsItemshowPreviousNewsItem不是预期的。当然,这是不期望的,因为我正在测试,我只希望在生产代码本身发生某些事情。

嘲笑概念的哪个部分我理解不正确?

回答

2

模拟被测试的类通常会造成混淆,但是如果你想这样做,你需要一个“部分模拟”,这样你就可以调用方法而不用剔除它们并让它们执行正常的方法。

这似乎在OCMock根据docs支持。

+0

谢谢 - 这是正确的。但不幸的是,iOS项目倾向于积累“行为驱动”方法,而不是具有明确返回值的函数。这样我只能测试方法调用的正确调用,而不是我期望的结果。也许我应该考虑重构这个。 ;-) –

+0

你自己的答案似乎表明你想出了如何用部分模拟来做到这一点。对不起,如果它不明确,但我想指出你的确如此,但我也在说,不要模拟你正在测试的课程会更好。当你发现需要这个时重构几乎总是一个好主意。 –

+0

没错。这个想法出现在我的脑海里,可能在你发布这个的同时。我要标记你的答案是正确的,但我只是不想在评论中发布整个代码(这是不可能的)。非常感谢你! –

2

我找到了解决方案。在对象上使用partialMock完全是我想要的。这样,我明确定义的调用被模拟,并且我调用了“未模拟”对象上正在测试的方法。

- (void)testShowNextOrPreviousItemShouldReloadWebView { 

    NewsItemDetailsViewController *sut = [[NewsItemDetailsViewController alloc] init]; 

    id mockSut = [OCMockObject partialMockForObject:sut]; 

    [[[mockSut expect] andReturn:@"http://www.someurl.com"] nextNewsUrl]; 
    [[mockSut expect] loadWebViewContent]; 

    [[[mockSut expect] andReturn:@"http://www.someurl.com"] previousNewsUrl]; 
    [[mockSut expect] loadWebViewContent]; 

    [sut showNextNewsItem]; 
    [sut showPreviousNewsItem]; 

    [mockSut verify]; 
} 
相关问题