OCMock测试一个对象被分配并在其上调用一个方法

时间:2013-07-29 04:29:56

标签: ios objective-c mocking tdd ocmock

我终于在我正在研究的项目上施加了一些TDD,并且遇到了问题...我知道我想要的代码但不知道如何测试它:)

我正在寻找的实现是:

- (void) doSomething
{
    FooBuilder *foo = [[FooBuilder alloc] init];
    [foo doSomethingElseWithCompletionBlock:^{
        [self somethingDone];
    }];
}

所以我希望我的测试验证a)测试中的方法分配一个新的FooBuilder和b)该方法然后调用新对象的方法。

我该如何解决这个问题?我开始尝试模拟alloc类方法,但很快就确定了这条路是疯狂的。

注意我没有使用此测试测试FooBuilder本身,只是合作就在那里。

2 个答案:

答案 0 :(得分:1)

通常情况下,依赖注入用于提供一个完全形成的对象,说“不是要求这个对象,而是在这里,使用它”。但在这种情况下,我们希望能够实例化一个新对象。因此,我们所要做的就是注入一个对象,而不是注入一个对象。 “不是创建一个特定的类,而是在这里实例化其中一个。”

依赖注入有两种主要形式:“构造函数注入”(我将坚持使用术语“构造函数”,即使Objective-C将其分为分配和初始化)和“属性注入”。

对于构造函数注入,请在初始化程序中指定类:

- (instancetype)initWithFooBuilderClass:(Class)fooBuilderClass;

对于属性注入,请在属性中指定类:

@property (nonatomic, strong) Class fooBuilderClass;

构造函数注入更清晰,因为它使依赖性变得明显。但你可能更喜欢注入房产。有时我会从另一个方向开始重构,改变主意。

无论哪种方式,您都可以使用默认初始值设定项来调用-initWithFooBuilderClass:或将属性设置为[FooBuilderClass class]

然后doSomething会这样开始:

- (void)doSomething
{
    id foo = [[self.fooBuilderClass alloc] init];
    ...

答案 1 :(得分:0)

我最后通过向FooBuilder添加一个新的类方法来解决这个问题,该方法将完成块作为参数。所以我有效地将实例化和方法调用从我的测试对象中移出到协作者对象中。现在我可以模拟那个单类方法调用。

我认为这最终会比我开始的设计略胜一筹;现在需要对该类的用户隐藏需要实例化的新FooBuilder的详细信息。它也很简单。

它确实具有保持我的测试对象和FooBuilder类之间强耦合的属性。也许这会让我不知所措 - 但是我让YAGNI下注它不会。