"Python Function Decorator" для target-c, чтобы изменить поведение метода - PullRequest
0 голосов
/ 10 июля 2019

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

Если в Python я бы использовал декоратор, чтобы изменить поведениеmethod.

Например, моя цель: улучшить покрытие кода путем автоматического тестирования нескольких входных данных.

Псевдокод:

@implementation SomeTestSuiteClass
// If in python, I would add a decorator here to change the behavior of the following method
-(void)testSample1 {
  input = SpecialProvider();
  output = FeatureToTest(input);
  SpecialAssert(output);
}
@end

Что я хочу: во время тестаметод testSample1 будет вызываться несколько раз.Каждый раз SpecialProvider будет излучать разные входные данные.То же самое для SpecialAssert, который может проверять вывод, соответствующий заданному вводу.

SpecialProvider и SpecialAssert будут API под моим контролем / владением (т.е. я их пишу).SomeTestSuiteClass вместе с testSample1 будет записан пользователем (т.е. автором тестов).

Есть ли способ для Objective-C достичь "того, что я хочу" выше?

1 Ответ

0 голосов
/ 10 июля 2019

Вы можете смоделировать объекты и / или их методы, используя target-c runtime или некоторые сторонние фреймворки. Я препятствую этому все же. Это признак плохого выбора архитектуры в первую очередь. Основная проблема в вашем подходе - скрытые зависимости в вашем коде, непосредственно ссылающиеся на SpecialProvider & SpecialAssert символов напрямую. Гораздо лучший способ это было бы так:

-(void)testSample1:(SpecialProvider*)provider assert:(BOOL (^)(parameterTypes))assertBlock {
  input = provider;
  output = FeatureToTest(input);
  if (assertBlock != nil) {
      assertBlock(output);
  }
}

Поскольку Objective-c не поддерживает значения аргументов по умолчанию, как Swift, вы можете эмулировать его с помощью:

-(void)testSample1 {
    [self testSample1:DefaultSpecialProvider() assert:DefaultAssert()];
}

не вызывать явное -(void)testSample1:(SpecialProvider*)provider assert:(BOOL (^)(parameterTypes))assertBlock все время, однако в тестах вы бы всегда использовали явный вариант с двумя аргументами, чтобы разрешить замену реализации (ей), которая не тестируется.

Идея дальнейшего совершенствования:
Поместите SpecialProvider и SpecialAssert позади протоколов (то есть эквивалент интерфейсов в других языках программирования), чтобы вы могли легко обмениваться реализацией.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...