具有从测试方法调用的方法的类的 OCMock
我正在尝试测试一种实例化 MFMailComposeViewController 实例的方法。正在测试的方法调用 MFMailComposeViewController
的多个方法,包括 setSubject:
。
我想测试 setSubject 是否发送了特定的 NSString,在本例中为@“Test Message”。
无论我在模拟存根中为预期字符串指定什么,都不会失败。
在单元测试类中:
#import <OCMock/OCMock.h>
- (void)testEmail {
TestClass *testInstance = [[TestClass alloc] init];
id mock = [OCMockObject mockForClass:[MFMailComposeViewController class]];
[[mock stub] setSubject:@"Test Message"];
[testInstance testMethod];
}
在 TestClass 中:
- (void)testMethod {
MFMailComposeViewController *mailComposeVC = [[MFMailComposeViewController alloc] init];
[mailComposeVC setSubject:@"Bad Message"];
}
Test Suite 'Email_Tests' started at 2011-09-17 18:12:21 +0000
Test Case '-[Email_Tests testEmail]' started.
Test Case '-[Email_Tests testEmail]' passed (0.041 seconds).
测试应该失败。
我正在 iOS 模拟器中对此进行测试,并在设备上得到相同的结果。
我做错了什么?有什么办法可以做到这一点吗?
I am trying to test a method that instantiates an instance of MFMailComposeViewController
. The method being tested calls several methods of MFMailComposeViewController
including setSubject:
.
I want to test that setSubject is sent a specific NSString, in this case @"Test Message".
No matter what I specify for the expected string in the mock stub there is no failure.
In the Unit Test class:
#import <OCMock/OCMock.h>
- (void)testEmail {
TestClass *testInstance = [[TestClass alloc] init];
id mock = [OCMockObject mockForClass:[MFMailComposeViewController class]];
[[mock stub] setSubject:@"Test Message"];
[testInstance testMethod];
}
In TestClass:
- (void)testMethod {
MFMailComposeViewController *mailComposeVC = [[MFMailComposeViewController alloc] init];
[mailComposeVC setSubject:@"Bad Message"];
}
Test Suite 'Email_Tests' started at 2011-09-17 18:12:21 +0000
Test Case '-[Email_Tests testEmail]' started.
Test Case '-[Email_Tests testEmail]' passed (0.041 seconds).
The test should have failed.
I am testing this in the iOS simulator and get the same result on a device.
What am I doing wrong? Is there some way to accomplish this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您创建了一个模拟,但从未将其传递给被测试的类,或要求模拟验证自身。您需要某种形式的依赖注入来表示:“不要使用 MFMailComposeViewController,而是使用我给您的其他东西。”
这是一种方法。在被测试的类中,不是直接分配 MFMailComposeViewController,而是通过工厂方法获取它,如下所示:
这是实现。您正在泄漏,因此请注意工厂方法返回一个自动释放的对象。
在测试方面,我们创建一个覆盖工厂方法的测试子类,以便它提供我们想要的任何内容:
现在我们准备好进行测试了。我做了一些不同的事情:
这里是测试:
为了完整性,我们需要一个最终测试,这是为了保证实际类中的工厂方法返回我们期望的结果:
You create a mock, but never pass it to the class under test, or ask the mock to verify itself. You need some form of dependency injection to say, "Instead of using MFMailComposeViewController, use this other thing I'm giving you."
Here's one way to do that. In the class under test, instead of allocating MFMailComposeViewController directly, get it through a factory method, like this:
Here's the implementation. You were leaking, so note that the factory method returns an autoreleased object.
Over on the testing side, we create a testing subclass that overrides the factory method so it provides whatever we want it to:
Now we're ready for the test. I do a few things differently:
Here's the test:
For completeness, we need one final test, and that's to guarantee that the factory method in the actual class returns what we expect:
Jon Reid 的方法是一种合理的方法,尽管将
mailComposeViewController
设为类方法似乎会使它变得复杂。在测试代码中对其进行子类化意味着您将始终在测试时获得模拟版本,这可能不是您想要的。我会把它作为一个实例方法。然后,您可以在测试时使用部分模拟来覆盖它:如果将其保留为类方法,您可能会考虑将其设为静态全局并公开覆盖它的方法:
然后,您的测试将类似于 Jon 的示例:
Jon Reid's is a reasonable approach, though it seems that making
mailComposeViewController
a class method complicates it. And subclassing it in your test code means you'll always get the mocked version at test time, which may not be what you want. I'd make it an instance method. Then you can use a partial mock to override it at test time:If you keep it as a class method, you might consider making it a static global and exposing a way to override it:
Then, your test would be similar to Jon's example: