使用SKProduct测试Swift代码

故事

旧的可信赖的源代码-很好,它可以正常运行很多年。 是的,只有很少的无法解释的方法,没有人记得这是什么以及拥有它们的原因是什么。 还是那是一个错误修复程序? 与其保持原样,而且完全不要触摸它。

上周,我不得不重构一个古董应用程序内购买经理—用Objective-C编写的应用程序非常尊重您的要求,60%包含单元测试。 为了减少任务的繁琐性,我为自己找到了另外一个动机–不仅重构了旧代码,而且还用Swift重新编写了代码。 现在,这项任务听起来更具吸引力。

问题

如果您对主题非常了解(Apple应用程序内购买),那么编写具有基本功能的应用程序内购买经理(控制器/帮助者/其他)很容易:
–从AppStore检索产品信息(标题,描述,价格等)
–在App Store上购买产品
– 恢复购买。

我跳过了有关购买的冗长的基本解释,直接解决了这个问题:以前的Objective-C实现具有良好的单元测试范围。 OSMock框架实际上可以模拟所有内容,包括必要时的系统类。 例如,以下代码创建一个SKProduct类的模拟,并为productIdentifier方法创建一个存根:

 静态NSString * productIdentifier = @“ com.test.identifier”; 
id产品= [OCMockObject mockForClass:[SKProduct类]];
[[[product stub] andReturn:productIdentifier] productIdentifier];

再举一个例子,下面的代码允许我测试价格处理:

  id产品= [OCMockObject mockForClass:[SKProduct类]]; 
NSDecimalNumber * price = [NSDecimalNumber decimalNumberWithString:@” 1“];
[[[产品存根]和退货:价格]价格];
NSLocale * locale = [NSLocale localeWithLocaleIdentifier:@” en_US”];
[[[产品存根]和Return:locale] priceLocale];

新代码应在Swift中。 此代码也必须是可测试的。

如何在Swift中模拟SKProduct类?

解决方案是扩展SKProduct类:

 导入StoreKit 
 公共扩展SKProduct { 

便利init(标识符:字符串,价格:字符串,priceLocale:区域设置){
self.init()
self.setValue(identifier,forKey:“ productIdentifier”)
self.setValue(NSDecimalNumber(string:price),forKey:“ price”)
self.setValue(priceLocale,forKey:“ priceLocale”)
}
}

上面的扩展添加了一个便捷的初始化器,该初始化器允许使用以下预定义的标识符,价格和语言环境设置SKProduct实例:

  let product = SKProduct(标识符:“ com.test.one”,价格:“ 1.23”,priceLocale:语言环境(标识符:“ en_US”)) 

现在,我可以创建一个SKPayment实例并将其添加到事务观察器中:

 让付款= SKPayment(产品:产品) 
Observer.add(付款)

其余的一切都很容易并且众所周知。 如果有兴趣,可以在公共git存储库中找到:Simple Purchase。

参考文献

  1. 指南和示例代码。 应用内购买编程指南
  2. API参考。 StoreKit。
  3. WWDC 2016.会议702
  4. 技术说明TN2387。 应用内购买最佳做法