我想测试类型为 Basket
的对象篮子的反序列化,其中包含类型为 AProduct
的对象数组。
我所有的产品类都继承自抽象类 AProduct
。
渐渐地,我会有越来越多的产品类别,每个类别都有不同的属性。
目前,这就是我测试篮子反序列化的方式:
Basket *oldBasket = BasketInstance;
[BasketInstance resetBasket]; // BasketInstance is a macro which points on the current Basket in singleton.
[BasketInstance deserializeItself:[self getBasketSerializedForTest]]; // getBasketSerializedForTest return a dictionnary of the same basket serialized.
XCTAssertTrue([BasketInstance isEqual:oldBasket], @"Basket deserialization is no correct");
此实现的主要问题是我必须重写 Basket
类中的 isEqual
方法,并且对于每个 AProduct
对象,重写 isEqual
方法来检查所有的属性。我认为这是非常危险的,因为如果我或其他开发人员添加了一个新属性并忘记在 isEqual
方法上检查该属性的值,则篮子的单元测试可能会成功,但反序列化失败.
是否有任何解决方案可以避免这种风险?虽然我解析了类的所有属性并为每个属性运行 isEqual
方法,但我希望有更好的解决方案。
谢谢
最佳答案
标准的 OOP 方法是每个子类测试它自己的属性。所以每个属性都会被检查一次。我认为这很简单,也很容易。完全没有危险,而且比处理运行时更简单。
@interface AProduct : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *stockIdentifier;
@end
@implementation AProduct
-(BOOL)isEqual:(id)object
{
BOOL equal= [object isKindOfClass:[self class]]
&& [[(AProduct *)object name] isEqualToString:self.name]
&& [[(AProduct *)object stockIdentifier] isEqualToString:self.stockIdentifier];
return equal;
}
@end
@interface Shirt : AProduct
@property (nonatomic, copy) NSString *size;
@property (nonatomic, copy) NSString *color;
@end
@implementation Shirt
-(BOOL)isEqual:(id)object
{
BOOL equal = [super isEqual:object];
if (equal) {
equal = [[(Shirt *)object size] isEqualToString:self.size]
&& [[(Shirt *)object color] isEqualToString:self.color];
}
return equal;
}
并且由于您担心单元测试:您应该编写一个我认为也会失败的相等性测试。如果红色和蓝色衬衫确实评估为相等,则此测试失败并且您知道您必须查看 -isEqual:
假设我只是将 AProduct 子类化为 Shirt。 AProduct 有它的 -isEqual:
工作,但我还没有在 Shirt 中覆盖和扩展它。
现在我编写如下测试方法:
- (void)testShirtInEquality
{
Shirt *redShirt = [[Shirt alloc] init];
redShirt.name =@"Shirt";
redShirt.stockIdentifier =@"shirt";
redShirt.size = @"XXL";
redShirt.color = @"red";
Shirt *blueShirt = [[Shirt alloc] init];
blueShirt.name =@"Shirt";
blueShirt.stockIdentifier =@"shirt";
blueShirt.size = @"XXL";
blueShirt.color = @"blue";
XCTAssertNotEqualObjects(redShirt, blueShirt, @"not equal!");
}
它将失败,因为 -isEqual:
的 AProduct 实现将触发并发现一切都相同。现在我知道我必须编写代码来使这个测试通过,并且我添加了
-(BOOL)isEqual:(id)object
{
BOOL equal = [super isEqual:object];
if (equal) {
equal = [[(Shirt *)object size] isEqualToString:self.size]
&& [[(Shirt *)object color] isEqualToString:self.color];
}
return equal;
}
测试通过。
所以实际上答案不是写一个动态的-isEqual:
方法,而是紧紧地坚持测试驱动开发。
简单回顾一下:
TDD华尔兹
- 写一个失败的测试
- 编写最简单的代码来通过测试
- 重构生产和测试代码
- 并重复
关于objective-c - 如何在 objective-c 中比较两个具有很多属性的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22858350/