2013-07-29 1 views
4

Я, наконец, налагаю TDD на проект, над которым я работаю, и бегу в края ... Я знаю код, который я хочу, но не как тест на это :)OCMock проверяет объект на выделение и вызывается метод

реализация Я ищу это:

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

Так что я хочу, чтобы мой тест, чтобы проверить, что а) метод испытуемый выделяет новый FooBuilder и б) этот метод, то вызовы метод нового объекта.

Как это сделать? Я начал с пути, пытаясь издеваться над методом класса alloc, но быстро определил, что по этому пути лежит безумие.

Примечание. Я не тестировал FooBuilder сам с этим тестом, просто чтобы сотрудничество было.

ответ

1

Обычно инъекция зависимости используется для обеспечения полностью сформированного объекта, говоря «вместо того, чтобы просить этот объект, здесь вы идете, используйте это». Но в этом случае мы хотим создать экземпляр нового объекта. Поэтому вместо того, чтобы вводить объект, все, что нам нужно сделать, это ввести класс. «Вместо создания определенного класса, здесь вы идете, создайте один из них».

Существуют две основные формы инъекций зависимостей: «инъекция конструктора» (я буду придерживаться термина «конструктор», даже если Objective-C разделяет это на распределение и инициализацию) и «инъекция свойств».

Для инъекций конструктора, указать класс в инициализаторе:

- (instancetype)initWithFooBuilderClass:(Class)fooBuilderClass; 

Для инъекций собственности, определить класс в свойстве:

@property (nonatomic, strong) Class fooBuilderClass; 

Конструктор инъекции понятнее, потому что это делает зависимость очевидно. Но вы можете предпочесть вложение свойств. Иногда я начинаю один путь и рефакторинг по отношению к другому, меняя свое мнение.

В любом случае вы можете иметь инициализатор по умолчанию, который либо вызывает -initWithFooBuilderClass:, либо задает свойство, [FooBuilderClass class].

Тогда doSomething бы начать так:

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

Jon, спасибо за ваше внимание и подробный ответ - но я думаю, что здесь что-то не хватает. Вы диагностируете связь между тестируемым классом и классом 'FooBuilder' как проблему.При этом я чувствую, что вы делаете что-то просто намного сложнее. У меня есть панель объектов, которая отображает Foos; для этого ему нужно построить Foo с FooBuilder. Я чувствую, что вы просите меня ввести общность. Мне не нужно только упрощать тестирование. – dpassage

+0

Я проснулся сегодня утром, осознав, что проблема на самом деле является просто инъекцией зависимости класса. Поэтому я полностью переписал свой ответ; попробуйте его для размера. ... Если он все еще будет чересчур сложным, сообщите мне, и я попытаюсь объяснить дальше. –

+0

Я все еще думаю, что вы не получаете то, что я прошу. Мой вопрос заключается в том, как управлять OCMock API, чтобы гарантировать, что мой объект-тест делает правильные исходящие вызовы. Вы по-прежнему пытаетесь ввести общность в класс, который ему не нужен. – dpassage

0

Я в конечном итоге решение, добавив новый метод класса к FooBuilder, который принимает блок завершения в качестве аргумента. Поэтому я фактически переместил вызов экземпляра и метода из моего объекта в тестовый объект. Теперь я могу издеваться над этим вызовом метода одного класса.

Я думаю, что это выглядит немного лучше, чем с того, с чего я начал; информация о том, что должен быть создан новый объект FooBuilder, скрыт от пользователей этого класса. Это тоже довольно просто.

У этого есть свойство, что оно поддерживает сильную связь между моим объектом-испытанием и классом FooBuilder. Может быть, это укусит меня по дороге, но я делаю ставку YAGNI на то, что этого не произойдет.

+0

Я рад, что вы нашли что-то, что работает. Но вы столкнетесь с той же проблемой в другом месте, и вам нужно будет использовать Injection Dependency. Я приведу еще один пример из примера: http://stackoverflow.com/questions/13711911/unit-testing-example-with-ocunit/ –

+0

Я уверен, что буду, и это хорошая техника, чтобы знать. В этом случае, однако, действительно было похоже, что добавление этой общности сделает код более сложным для понимания. Спасибо за вашу помощь. Я уже использую некоторые подсказки с вашего сайта в своем приложении. :) – dpassage

Смежные вопросы