一个单元测试代码如何与Core Bluetooth API交互? [英] How does one unit test code that interacts with the Core Bluetooth APIs?

查看:69
本文介绍了一个单元测试代码如何与Core Bluetooth API交互?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想对作为 CBPeripheralManager 类的 CBPeripheralManagerDelegate 的类进行单元测试。通常,为了消除外部类的依赖关系,我将通过通过类初始化程序或通过属性传入来使用某种形式的依赖关系注入。在处理基于单例的API时,我已经能够使用Kiwi之类的库对返回单例的类级别方法进行存根(即 [ClassName stub:@selector(sharedInstance)andReturn:myStubbedInstance] )。模拟 CBPeripheralManager 时,问题在于其初始化程序采用委托实例。因此,使用我的课程的任何代码都需要执行以下操作:

I would like to unit test a class that acts as a CBPeripheralManagerDelegate to the CBPeripheralManager class. Typically, in order to stub out an external class dependency, I would use either a form of dependency injection by passing in via the class initializer or via a property. When dealing with singleton-based API's, I have been able to use libraries like Kiwi to stub the class level method that returns the singleton (i.e. [ClassName stub:@selector(sharedInstance) andReturn:myStubbedInstance]). The issue in the case of mocking CBPeripheralManager is that its initializer takes the delegate instance. So any code that uses my class would need to do something like this:

PeripheralManagerWrapper *wrapper = [[PeripheralManagerWrapper alloc] init];
CBPeripheralManager *peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:wrapper queue:nil options:nil];
wrapper.peripheralManager = peripheralManager;

然后,对我的 PeripheralManagerWrapper 类进行单元测试,我可以简单地实例化它并传递一个模拟的 CBPeripheralManager 。但是,我不希望要求包装对象的任何调用代码都必须经过此设置。有没有更好的模式来处理这种情况?我同时使用了Kiwi和OCMockito,但似乎都没有提供此功能,可能只是取消了 alloc init CBPeripheralManager 的方法,然后在 PeripheralManagerWrapper
的初始值设定项中实例化该实例。

Then, for unit testing my PeripheralManagerWrapper class, I could simply instantiate it and pass in a mocked CBPeripheralManager. However, I don't like requiring any calling code of my wrapper object to have to go through this setup. Is there a better pattern for dealing with this situation? I've used both Kiwi and OCMockito, but neither seem to provide this functionality short of maybe stubbing the alloc and init methods of CBPeripheralManager and then just instantiating the instance in the PeripheralManagerWrapper 's initializer.

推荐答案

恕我直言,Core Bluetooth API非常适合单元测试。所有委托回调都使用管理器和相关参数,因此,如果遵循使用这些参数而不是内部状态的模式,则可以传递任何所需的信息。使用模拟对象是执行此操作的最佳方法。在进行单元测试时,您不应尝试模仿经理的行为。您应该专注于验证代码与API的交互,仅此而已。

IMHO, the Core Bluetooth APIs are perfect match for unit testing. All the delegate callbacks take the manager and the relevant parameters so if you follow the pattern that you use these arguments instead of the internal state, then you will be able to pass in anything you want. Using mock objects is the best way to do this. While unit testing, you shouldn't try to mock the behavior of the managers. You should focus on verifying the interaction of your code with the API and nothing more.

包装器可能更适合集成测试。但实际上,根据我的经验,最好手动完成Core Bluetooth代码的集成测试。堆栈不够稳定,无法进行可靠的测试,而且测试代码也必须针对堆栈错误进行强化,这确实很难,因为很显然,仅通过查看API便无法记录或预测这些错误。另一方面,您的测试代码也必须模拟堆栈的错误行为。在某些情况下,虽然可能,但是如果不超过您要测试的代码,那么测试代码就会变得同样复杂。

Wrappers may better suit integration testing. But actually, the integration testing of Core Bluetooth code is better done manually to my experience. The stack is not stable enough to allow for reliable testing, and the test code would have to be fortified against the stack errors too which is really hard as, obviously, those are not documented or predictable just by looking at the APIs. While on the other hand, your test code would have to simulate the erroneous behavior of the stack too. There may be cases when it is possible but the test code will be just as complex if not more than the code you are testing.

这篇关于一个单元测试代码如何与Core Bluetooth API交互?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆