Polidea / RxBluetoothKit

iOS & OSX Bluetooth library for RxSwift
Apache License 2.0
1.41k stars 371 forks source link

How to mock a CentralManager class #340

Open gtatgh opened 5 years ago

gtatgh commented 5 years ago

Is your feature request related to a problem? Please describe. I have a wrapper class BluetoothHandler around of CentralManager which configure the use of CentralManager, like in your example. So, how can I mock CentralManager in unit tests e.g. for scanning?

Describe the solution you'd like I would like to test the logic of BluetoothHandler.

class BluetoothHandlerTest: XCTestCase {
    func testStartScan() {
        let cm = CentralManager()
        let bh = BluetoothHandler(centralManager: cm)
        bh.startScan()
        // Here I want to inject mocked data
        cm.delegateWrapper.didDiscoverPeripheral(CBPeripheralMock(), nil, nil)
        XCTAssertEqual(1, bh.scannedPeripherals.count)
    }
}

Additional context

class BluetoothHandler {
    /**
     A list of scanned peripherals.
     */
    public let scannedPeripherals = [ScannedPeripheral]()

    ...

    init(centralManager: CentralManager) {
        self.centralManager = centralManager
    }

    func startScan() {
        scanningDisposable = centralManager
            .observeState()
            .startWith(centralManager.state)
            .filter {
                $0 == .poweredOn
            }
            .flatMap { _ -> Observable<ScannedPeripheral> in
                self.centralManager.scanForPeripherals(
                    withServices: nil,
                    options: nil)
            }.subscribe(
                onNext: { scannedPeripheral in
                    debugPrint("found a  new peripheral with name \(String(describing: scannedPeripheral.peripheral.name))")

                    scannedPeripherals.append(scannedPeripheral)
            })
    }
...
}
minixT commented 5 years ago

Hi @gtatgh Do you want to add tests to RxBluetoothKit library or to your project? If you want to use CentralManager mock in RxBluetoothKit tests you should use _CentralManager instead. This is autogenerated mock of CentalManager class. Example how it is used can be found in tests in the Tests folder. If you want to mock CentralManager in your own project you can create a protocol with methods which you want to use in your tests and use it instead CentralManager in your code. CentralManager should implement this protocol and you can also create a mock which also implements this protocol and use it in your tests.. If you are interested in more details please ask.

gtatgh commented 5 years ago

Hello @minixT, yes I want to mock CentralManager in my own project, specially in BluetoothHandler. I can create a protocol and extend it in BluetoothHandler. What I want is to receive e.g. ScannedPeripheral from CentralManager.

JamesRoome commented 5 years ago

@minixT I am about to do some testing and was looking into this... My question to you is: If it is the case that you recommend using a protocol for mocking, why does the main codebase not use that exact same approach? Peripheral could have been a protocol, but it isn't. Why?