我一直在使用Objective C和Cocoa/iOS并像测试者一样进行测试。 (Definition)在ObjectiveC中做BDD时嘲笑合作者的最好方法是什么?
- 我想嘲笑使用OCMock的对象的协作者。
有目标C做这两种方式我所知道的:
- 依赖注入
- 设置内部状态 - 无论是通过访问器或setValue方法:forKey:
我应该使用哪一种?
我不喜欢这些。但我必须使用一个...除非我还没有其他选项。
1.依赖注入
这杂波我的代码,尤其是当SUT有2/3的合作者。如果SUT需要通过1/2参数,事情看起来确实非常混乱。
我明白,远远超过3,有太多的依赖关系,对象应该分成其他部分...但即使有2个依赖关系和1个参数,它仍然是丑陋的罪过。
2.设置内部状态
这打乱了类的内部 - 我觉得这是一个很大的禁忌测试。
访问者绝对不在 - 他们暴露的数据是没有人应该知道的。 我可以使用setValue:forKey:...但这感觉像一个可怕的黑客。
这也意味着我必须初始化SUT,然后换出真正的模拟合作伙伴,然后运行测试中的方法,这感觉很混乱。
我的问题
什么是做BDD时,模拟出的目标C合作者的最好方法是什么?
代码
惩戒使用的setValue:forKey:
@interface JGCompositeCommand : JGCommand <JGCompositeCommandProtocol> {
NSMutableArray *commands;
JGCommandFinderFactory *commandFinderFactory;
}
-(id <JGCommandProtocol>)initWithName:(NSString *)name_ recoverer:(id <JGCommandRecoveryProtocol>)recoverer_ executor:(id <JGCommandExecutorProtocol>)executor_;
@end
@implementation JGCompositeCommand
-(id)initWithName:(NSString *)name_ recoverer:(id)recoverer_ {
self = [super initWithName:name_ recoverer:recoverer_];
if (self) {
commands = [NSMutableArray array];
commandFinderFactory = [[JGCommandFinderFactory alloc] init];
}
return self;
}
-(id <JGCommandProtocol>)commandWithName:(NSString *)name_ {
return [[commandFinderFactory commandFinderWithCommandName:name_ andCommands:commands] findCommandWithName];
}
@end
@interface JGCommandTestCase : SenTestCase {
JGCompositeCommand *compositeCommand;
OCMockObject *commandFinderFactoryMock;
}
@end
@implementation JGCommandTestCase
-(void)setUp {
[super setUp];
compositeCommand = [[JGCompositeCommand alloc] initWithName:@"" recoverer:nil];
commandFinderFactoryMock = [OCMockObject mockForClass:[JGCommandFinderFactory class]];
// Hack alert! Ugh.
[compositeCommand setValue:commandFinderFactoryMock forKey:@"commandFinderFactory"];
}
-(void)testGivenCommandNotFoundShouldThrow {
// ** Setup **
[[[commandFinderFactoryMock expect] andReturn:...] commandFinderWithCommandName:... andCommands:...];
// ** Execute **
[compositeCommand commandWithName:@"Blah"];
// ** Asserts **
[commandFinderFactoryMock verify];
}
@end
我很困惑 - 当然,这意味着每一位合作者都是单身?这肯定意味着大多数班级都变成了单身人士。我认为一个单身人士是一个反模式。 – 2012-02-19 10:17:08
我想这取决于你的意思是“每一位合作者”。当然还有其他的获取和配置对象的模式。您选择的取决于您的需求。例如,笔尖是依赖注入的一种形式,所以在笔尖中配置的任何东西都可以在测试时注入。至于单身人士作为反模式,我认为主要的批评是他们很难作为协作者测试,这种方法试图解决这个问题。看看http://blog.securemacprogramming.com/2011/02/on-singletons/。 – 2012-02-20 18:05:33