如何在iOS单元测试中公开私有属性?

如何在iOS单元测试中公开私有属性?,ios,unit-testing,Ios,Unit Testing,我试图测试一个类的方法,该类使用了该类的一些私有属性。我四处寻找如何在单元测试中访问它们的最佳实践,并决定在测试实现文件中为类添加一个类别。尽管如此,它仍然不允许我访问它们,我收到了“未经CGONized的选择器发送到实例”错误 我的实现类属性定义(位于ImplementationClass.m文件的顶部): 在我的测试类顶部的类别: //interface to expose private variables of test case class @interface Implementat

我试图测试一个类的方法,该类使用了该类的一些私有属性。我四处寻找如何在单元测试中访问它们的最佳实践,并决定在测试实现文件中为类添加一个类别。尽管如此,它仍然不允许我访问它们,我收到了“未经CGONized的选择器发送到实例”错误

我的实现类属性定义(位于ImplementationClass.m文件的顶部):

在我的测试类顶部的类别:

//interface to expose private variables of test case class
@interface ImplementationClass (Test)
    @property(readwrite,assign) TWPLoadUnitEnum loadUnit;
    @property(readwrite,assign) BOOL recosMatchTargets;
@end
我访问属性的位置:

        ImplementationClass *realRecosModal = [[ImplementationClass alloc] 
initWithNibName:@"ImplementationClassVC" bundle:nil];
        [realRecosModal setLoadUnit:TWPLoadUnitKg]
我在调用“setLoadUnit”的行中得到错误。我没有正确地暴露私人财产吗

@interface ImplementationClass () {
    TWPLoadUnitEnum loadUnit;
    BOOL recosMatchTargets;
}
它们不是属性,而是IVAR。如果你想让它们成为财产,你需要

@interface ImplementationClass ()
@property (nonatomic) TWPLoadUnitEnum loadUnit;
@property (nonatomic) BOOL recosMatchTargets;
如果您想保留iVar,那么在单元测试中

@interface ImplementationClass () {
@public
    TWPLoadUnitEnum loadUnit;
    BOOL recosMatchTargets;
}
@end
  • 注意:这使用
    ()
    而不是
    (测试)
    。这看起来很奇怪,但会奏效的
  • 重要提示:您必须提供所有IVAR,并且它们必须按正确顺序排列,否则可能会导致意外行为(如随机崩溃)

我不确定让单元测试检查对象如何执行私有操作是否明智,因为这将使更改类执行其功能的方式变得更加困难

如果您的函数更改了私有属性,则此更改将影响任何其他公共属性/函数的行为。如果该属性的价值不影响任何公共功能,为什么要使用该属性以及为什么要更改它?结论:如果功能A改变了私有财产的价值,那么应该有一个功能B(可能与A相同)因为这种改变而改变行为

函数A的规范不应包含它设置私有属性x,而是它改变B的行为:

规范:如果使用参数值x调用public
A(intx)
,则`public intb{get;}应返回2*x

有几种方法可以实现这一点。您的测试不应该测试它是如何实现的。它应该测试规格。如果设计者认为最好将x保存在文件中而不是保存在私有成员中,那么仍然可以满足您的规范,但您的测试将失败

因此,指定私有项的值限制了类的开发人员,并使将来的更改更加困难


此外:在开发类和测试之前,您应该正式定义规范,因此您不知道哪些私有成员受函数的影响。测试的重点应该是是否符合规范,而不是如何实现功能。

谢谢!我不得不把它们换成房地产,然后一切都正常了。
@interface ImplementationClass () {
@public
    TWPLoadUnitEnum loadUnit;
    BOOL recosMatchTargets;
}
@end