【问题标题】:"python function decorator" for objective-c to change a method's behavior用于objective-c的“python函数装饰器”来改变方法的行为
【发布时间】:2019-07-10 00:31:34
【问题描述】:

我想修改某些函数的行为,而不是该函数的作者。我控制的是我可以要求作者遵循某种模式,例如使用基类,使用特定的装饰器、属性等。

如果在 python 中,我会使用装饰器来改变方法的行为。

例如,我的目标:通过自动测试多个输入数据来提高代码覆盖率。

伪代码:

@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 也一样,可以验证给定输入对应的输出。

SpecialProviderSpecialAssert 将是我控制/拥有的 API(即我编写它们)。 SomeTestSuiteClasstestSample1 将由用户(即测试编写者)编写。

Objective-C 有没有办法实现上面的“我想要的”?

【问题讨论】:

    标签: objective-c


    【解决方案1】:

    您可以使用 Objective-C 运行时或一些第三方框架来模拟对象和/或其方法。我不鼓励这样做。这首先是架构选择不佳的标志。您的方法中的主要问题是代码中直接引用的隐藏依赖项 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,但是在测试中您将始终使用显式的 2 参数变体以允许替换未在测试中的实现。

    进一步改进思路:
    SpecialProviderSpecialAssert 放在协议后面(即,相当于其他编程语言中的接口),以便您可以轻松地交换实现。

    【讨论】:

    • 感谢您改进设计!我没有得到的一个问题:在您的结构中,testSample1 如何使用来自 Provider 的不同输入数据多次运行?仅供参考,我进行了一些搜索,this 似乎是实现这一目标的好方向。
    • 您将使用 SpecialProvider* 的不同子类作为传递的参数来实现不同的行为。或者,arg 将是 SpecialProviding 协议类型,您将使用它的不同实现(例如 SpecialProviderForProductionSpecialProviderMock
    • 这是否意味着用户(测试编写者)必须多次显式调用testSample(例如在 for 循环中),每次测试一个输入?
    • testSample 不一定会在每个循环步骤中使用不同的参数调用(但如果您愿意,可以)。每个测试都应根据其需要通过 args。通过 args 而不是一些疯狂的依赖路径来执行此操作,您可以避免测试影响彼此结果的风险。你可以严格控制它。
    猜你喜欢
    • 2020-02-12
    • 2019-07-21
    • 1970-01-01
    • 2012-03-14
    • 2020-07-23
    • 2018-05-24
    • 2011-04-03
    • 2016-03-17
    • 1970-01-01
    相关资源
    最近更新 更多