From 0e23d3db370eb8a95a53680db0ef980cb910bd03 Mon Sep 17 00:00:00 2001 From: pawelByszewski Date: Tue, 3 Mar 2020 10:45:38 +0100 Subject: [PATCH 1/7] unit test for BleManager From 62093e5b01dec1d9e7e4dff28538b64ec9d46f4b Mon Sep 17 00:00:00 2001 From: pawelByszewski Date: Wed, 4 Mar 2020 02:09:17 +0100 Subject: [PATCH 2/7] peripheral tests --- test/peripheral_test.dart | 97 +++++++++++++++++++ ...scan_result.dart => scan_result_test.dart} | 0 2 files changed, 97 insertions(+) create mode 100644 test/peripheral_test.dart rename test/{scan_result.dart => scan_result_test.dart} (100%) diff --git a/test/peripheral_test.dart b/test/peripheral_test.dart new file mode 100644 index 00000000..1f28df88 --- /dev/null +++ b/test/peripheral_test.dart @@ -0,0 +1,97 @@ + +import 'package:flutter_ble_lib/flutter_ble_lib.dart'; +import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; +import 'package:mockito/mockito.dart'; +import 'package:test/test.dart'; + +class ManagerForPeripheralMock extends Mock implements ManagerForPeripheral {} + +void main() { + + const PERIPHERAL_NAME = 'Peripheral name'; + const PERIPHERAL_ID = 'peripheral id'; + + ManagerForPeripheralMock managerForPeripheral = ManagerForPeripheralMock(); + Peripheral peripheral; + + setUp(() { + Map json = { + 'name': PERIPHERAL_NAME, + 'id' : PERIPHERAL_ID + }; + peripheral = Peripheral.fromJson(json, managerForPeripheral); + }); + + group("Connect", () { + test('should pass defaut values to manager', () { + //when + peripheral.connect(); + + //then + verify(managerForPeripheral.connectToPeripheral( + PERIPHERAL_ID, + isAutoConnect: false, + requestMtu: 0, + refreshGatt: false, + timeout: null + )); + }); + + test('should pass given values to manager', () { + //given + var isAutoConnect = true; + var mtu = 33; + var refreshGatt = true; + var timeout = Duration(days: 4); + + //when + peripheral.connect( + isAutoConnect: isAutoConnect, + requestMtu: mtu, + refreshGatt: refreshGatt, + timeout: timeout + ); + + //then + verify(managerForPeripheral.connectToPeripheral( + PERIPHERAL_ID, + isAutoConnect: isAutoConnect, + requestMtu: mtu, + refreshGatt: refreshGatt, + timeout: timeout + )); + }); + }); + + group("Observe connection state", () { + test("should emit on every connection state change", () { + //given + var states = [ + PeripheralConnectionState.disconnected, + PeripheralConnectionState.connecting, + PeripheralConnectionState.connected + ]; + when(managerForPeripheral.observePeripheralConnectionState(any, any, any)) + .thenAnswer((_) => Stream.fromIterable(states)); + + //when + Stream connectionStateStream = peripheral.observeConnectionState(); + + //then + expect(connectionStateStream, emitsInOrder(states)); + }); + + test("should pass arguments to manager", () { + //given + var emitCurrentValue = true; + var completeOnDisconnect = true; + + //when + peripheral.observeConnectionState(emitCurrentValue: emitCurrentValue, completeOnDisconnect: completeOnDisconnect); + + //then + verify(managerForPeripheral.observePeripheralConnectionState(PERIPHERAL_ID, emitCurrentValue, completeOnDisconnect)); + }); + }); + +} \ No newline at end of file diff --git a/test/scan_result.dart b/test/scan_result_test.dart similarity index 100% rename from test/scan_result.dart rename to test/scan_result_test.dart From b972d8146ffc4728f109f831e1f629a20724beca Mon Sep 17 00:00:00 2001 From: pawelByszewski Date: Wed, 4 Mar 2020 03:36:16 +0100 Subject: [PATCH 3/7] peripheral tests --- test/peripheral_test.dart | 97 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/test/peripheral_test.dart b/test/peripheral_test.dart index 1f28df88..94681061 100644 --- a/test/peripheral_test.dart +++ b/test/peripheral_test.dart @@ -1,10 +1,13 @@ +import 'package:flutter/services.dart'; import 'package:flutter_ble_lib/flutter_ble_lib.dart'; import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; class ManagerForPeripheralMock extends Mock implements ManagerForPeripheral {} +class ServiceMock extends Mock implements Service {} +class CharacteristicMock extends Mock implements Characteristic {} void main() { @@ -94,4 +97,98 @@ void main() { }); }); + group("Connection checking", () { + [true, false].forEach((isConnected) { + test("returns isConneted information based on $isConnected returned by manager", () async { + //given + when(managerForPeripheral.isPeripheralConnected(any)) + .thenAnswer((_) => Future.value(isConnected)); + + //when + bool peripheralIsConnected = await peripheral.isConnected(); + + //then + expect(peripheralIsConnected, isConnected); + }); + }); + }); + + group("Discovery", () { + test("use given transactionId", () async { + //given + const transactionId = "86791384-"; + + //when + await peripheral.discoverAllServicesAndCharacteristics(transactionId: transactionId); + + //then + verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, transactionId)); + }); + + test("use generated transactionId", () async { + //when + await peripheral.discoverAllServicesAndCharacteristics(); + await peripheral.discoverAllServicesAndCharacteristics(); + + //then + verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, '1')); + verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, '2')); + }); + }); + + group("Services", () { + test("should return services", () async { + //given + List services = [ServiceMock(), ServiceMock()]; + when(managerForPeripheral.services(any)).thenAnswer((_) => Future.value(services)); + + //when + List fetchedServices = await peripheral.services(); + + //then + expect(fetchedServices, services); + }); + }); + + group("Characteristics", () { + test("should return characteristic for given service", () async { + //given + List characteristics = [CharacteristicMock(), CharacteristicMock()]; + const serviceUuid = "123uuid"; + when(managerForPeripheral.characteristics(any, serviceUuid)).thenAnswer((_) => Future.value(characteristics)); + + //when + List fetchedCharacteristic = await peripheral.characteristics(serviceUuid); + + //then + expect(fetchedCharacteristic, characteristics); + }); + }); + + group("Rssi", () { + test("use given transactionId", () async { + //given + const transactionId = "86791384-"; + const rssi = 23; + when(managerForPeripheral.rssi(any, transactionId)).thenAnswer((_) => Future.value(rssi)); + + //when + int obtainedRssi = await peripheral.rssi(transactionId: transactionId); + + //then + verify(managerForPeripheral.rssi(any, transactionId)); + expect(obtainedRssi, rssi); + }); + + test("use generated transactionId", () async { + //when + await peripheral.rssi(); + await peripheral.rssi(); + + //then + verify(managerForPeripheral.rssi(any, '1')); + verify(managerForPeripheral.rssi(any, '2')); + }); + }); + } \ No newline at end of file From 3688ca402d61f9732747d2bb2e2f4ccf0fae2ff3 Mon Sep 17 00:00:00 2001 From: pawelByszewski Date: Wed, 4 Mar 2020 11:33:26 +0100 Subject: [PATCH 4/7] refactor usage of TransactionIdGenerator - now it could be easily mocked for unit test --- lib/characteristic.dart | 14 ++++++----- lib/descriptor.dart | 7 ++++-- lib/peripheral.dart | 22 ++++++++++-------- lib/service.dart | 13 +++++++---- lib/src/internal_ble_manager.dart | 8 ++++--- lib/src/util/_transaction_id_generator.dart | 7 ++++-- test/peripheral_test.dart | 23 +++++++++++++++---- .../util/transcation_id_generator_test.dart | 7 ++++-- 8 files changed, 66 insertions(+), 35 deletions(-) diff --git a/lib/characteristic.dart b/lib/characteristic.dart index 070de610..fe87c5be 100644 --- a/lib/characteristic.dart +++ b/lib/characteristic.dart @@ -21,6 +21,7 @@ class Characteristic extends InternalCharacteristic { Service service; ManagerForCharacteristic _manager; + TransactionIdGenerator _transactionIdGenerator; /// The UUID of this characteristic. String uuid; @@ -41,9 +42,10 @@ class Characteristic extends InternalCharacteristic { bool isIndicatable; Characteristic.fromJson(Map jsonObject, Service service, - ManagerForCharacteristic manager) + ManagerForCharacteristic manager, {TransactionIdGenerator transactionIdGenerator = const TransactionIdGenerator()}) : super(jsonObject[_CharacteristicMetadata.id]) { _manager = manager; + _transactionIdGenerator = transactionIdGenerator; this.service = service; uuid = jsonObject[_CharacteristicMetadata.uuid]; isReadable = jsonObject[_CharacteristicMetadata.isReadable]; @@ -62,7 +64,7 @@ class Characteristic extends InternalCharacteristic { _manager.readCharacteristicForIdentifier( service.peripheral, this, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Writes to the value of this characteristic. @@ -80,7 +82,7 @@ class Characteristic extends InternalCharacteristic { this, value, withResponse, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a [Stream] of notifications/indications emitted by this @@ -95,7 +97,7 @@ class Characteristic extends InternalCharacteristic { _manager.monitorCharacteristicForIdentifier( service.peripheral, this, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a list of [Descriptor]s of this characteristic. @@ -110,7 +112,7 @@ class Characteristic extends InternalCharacteristic { _manager.readDescriptorForCharacteristic( this, descriptorUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Writes the [value] of a [Descriptor] identified by [descriptorUuid]. @@ -123,7 +125,7 @@ class Characteristic extends InternalCharacteristic { this, descriptorUuid, value, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); @override diff --git a/lib/descriptor.dart b/lib/descriptor.dart index 5e2e265a..427cea19 100644 --- a/lib/descriptor.dart +++ b/lib/descriptor.dart @@ -8,6 +8,7 @@ abstract class _DescriptorMetadata { class Descriptor extends InternalDescriptor { ManagerForDescriptor _manager; + TransactionIdGenerator _transactionIdGenerator; Characteristic characteristic; String uuid; @@ -15,8 +16,10 @@ class Descriptor extends InternalDescriptor { Map jsonObject, Characteristic characteristic, ManagerForDescriptor manager, + {TransactionIdGenerator transactionIdGenerator = const TransactionIdGenerator()} ) : super(jsonObject[_DescriptorMetadata.id]) { _manager = manager; + _transactionIdGenerator = transactionIdGenerator; this.characteristic = characteristic; uuid = jsonObject[_DescriptorMetadata.uuid]; } @@ -24,14 +27,14 @@ class Descriptor extends InternalDescriptor { Future read({String transactionId}) => _manager.readDescriptorForIdentifier( this, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); Future write(Uint8List value, {String transactionId}) => _manager.writeDescriptorForIdentifier( this, value, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); @override diff --git a/lib/peripheral.dart b/lib/peripheral.dart index c8298878..70251472 100644 --- a/lib/peripheral.dart +++ b/lib/peripheral.dart @@ -16,14 +16,16 @@ abstract class _PeripheralMetadata { class Peripheral { static const int NO_MTU_NEGOTIATION = 0; ManagerForPeripheral _manager; + TransactionIdGenerator _transactionIdGenerator; String name; String identifier; - Peripheral.fromJson(Map json, ManagerForPeripheral manager) + Peripheral.fromJson(Map json, ManagerForPeripheral manager, {TransactionIdGenerator transactionIdGenerator = const TransactionIdGenerator()}) : _manager = manager, name = json[_PeripheralMetadata.name], - identifier = json[_PeripheralMetadata.identifier]; + identifier = json[_PeripheralMetadata.identifier], + _transactionIdGenerator = transactionIdGenerator; /// Connects to the peripheral. /// @@ -82,7 +84,7 @@ class Peripheral { /// Optional [transactionId] could be used to cancel operation. Future discoverAllServicesAndCharacteristics({String transactionId}) => _manager.discoverAllServicesAndCharacteristics( - this, transactionId ?? TransactionIdGenerator.getNextId()); + this, transactionId ?? _transactionIdGenerator.getNextId()); /// Returns a list of [Service]s of this peripheral. /// @@ -103,7 +105,7 @@ class Peripheral { /// /// Optional [transactionId] could be used to cancel operation. Future rssi({String transactionId}) => - _manager.rssi(this, transactionId ?? TransactionIdGenerator.getNextId()); + _manager.rssi(this, transactionId ?? _transactionIdGenerator.getNextId()); /// Requests new MTU value for current connection and return the negotiation /// result on Android, reads MTU on iOS. @@ -118,7 +120,7 @@ class Peripheral { /// If MTU has been requested in [connect()] this method will end with [BleError]. Future requestMtu(int mtu, {String transactionId}) => _manager.requestMtu( - this, mtu, transactionId ?? TransactionIdGenerator.getNextId()); + this, mtu, transactionId ?? _transactionIdGenerator.getNextId()); /// Reads value of [Characteristic] matching specified UUIDs. /// @@ -135,7 +137,7 @@ class Peripheral { this, serviceUuid, characteristicUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Writes value of [Characteristic] matching specified UUIDs. @@ -157,7 +159,7 @@ class Peripheral { characteristicUuid, value, withResponse, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a list of [Descriptor]s for [Characteristic] matching specified UUIDs. @@ -191,7 +193,7 @@ class Peripheral { serviceUuid, characteristicUuid, descriptorUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Writes value of [Descriptor] matching specified UUIDs. @@ -214,7 +216,7 @@ class Peripheral { characteristicUuid, descriptorUuid, value, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a stream of notifications/indications from [Characteristic] @@ -236,7 +238,7 @@ class Peripheral { this, serviceUuid, characteristicUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); @override diff --git a/lib/service.dart b/lib/service.dart index 2b00d663..5c59d3c1 100644 --- a/lib/service.dart +++ b/lib/service.dart @@ -11,6 +11,7 @@ class Service extends InternalService { Peripheral peripheral; ManagerForService _manager; + TransactionIdGenerator _transactionIdGenerator; /// The UUID of this service. String uuid; @@ -19,10 +20,12 @@ class Service extends InternalService { Map jsonObject, Peripheral peripheral, ManagerForService managerForService, + {TransactionIdGenerator transactionIdGenerator = const TransactionIdGenerator()} ) : super(jsonObject[_ServiceMetadata.id]) { this.peripheral = peripheral; uuid = jsonObject[_ServiceMetadata.uuid]; _manager = managerForService; + _transactionIdGenerator = transactionIdGenerator; } /// Returns a list of [Characteristic]s of this service. @@ -51,7 +54,7 @@ class Service extends InternalService { characteristicUuid, value, withResponse, - transactionId ?? TransactionIdGenerator.getNextId()); + transactionId ?? _transactionIdGenerator.getNextId()); /// Reads the value of a [Characteristic] identified by [characteristicUuid]. /// @@ -67,7 +70,7 @@ class Service extends InternalService { peripheral, this, characteristicUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a [Stream] of values emitted by a [Characteristic] identified by @@ -86,7 +89,7 @@ class Service extends InternalService { peripheral, this, characteristicUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Returns a list of [Descriptor]s of a [Characteristic] identified by @@ -114,7 +117,7 @@ class Service extends InternalService { this, characteristicUuid, descriptorUuid, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); /// Writes the [value] of a [Descriptor] identified by [descriptorUuid] @@ -132,7 +135,7 @@ class Service extends InternalService { characteristicUuid, descriptorUuid, value, - transactionId ?? TransactionIdGenerator.getNextId(), + transactionId ?? _transactionIdGenerator.getNextId(), ); @override diff --git a/lib/src/internal_ble_manager.dart b/lib/src/internal_ble_manager.dart index 5234e89c..337490db 100644 --- a/lib/src/internal_ble_manager.dart +++ b/lib/src/internal_ble_manager.dart @@ -8,10 +8,12 @@ class InternalBleManager ManagerForCharacteristic, ManagerForDescriptor { FlutterBleLib _bleLib; + TransactionIdGenerator _transactionIdGenerator; - InternalBleManager() { + InternalBleManager({TransactionIdGenerator transactionIdGenerator = const TransactionIdGenerator()}) { _bleLib = FlutterBleLib(); _bleLib.registerManager(this); + _transactionIdGenerator = transactionIdGenerator; } @override @@ -36,11 +38,11 @@ class InternalBleManager @override Future enableRadio({String transactionId}) => - _bleLib.enableRadio(transactionId ?? TransactionIdGenerator.getNextId()); + _bleLib.enableRadio(transactionId ?? _transactionIdGenerator.getNextId()); @override Future disableRadio({String transactionId}) => - _bleLib.disableRadio(transactionId ?? TransactionIdGenerator.getNextId()); + _bleLib.disableRadio(transactionId ?? _transactionIdGenerator.getNextId()); @override Future bluetoothState() => _bleLib.state(); diff --git a/lib/src/util/_transaction_id_generator.dart b/lib/src/util/_transaction_id_generator.dart index b5270479..4ab7efd1 100644 --- a/lib/src/util/_transaction_id_generator.dart +++ b/lib/src/util/_transaction_id_generator.dart @@ -1,7 +1,10 @@ -abstract class TransactionIdGenerator { +class TransactionIdGenerator { static int _id = 0; - static String getNextId() { + + const TransactionIdGenerator(); + + String getNextId() { _id++; return _id.toString(); } diff --git a/test/peripheral_test.dart b/test/peripheral_test.dart index 94681061..0fa0751f 100644 --- a/test/peripheral_test.dart +++ b/test/peripheral_test.dart @@ -2,19 +2,22 @@ import 'package:flutter/services.dart'; import 'package:flutter_ble_lib/flutter_ble_lib.dart'; import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; +import 'package:flutter_ble_lib/src/util/_transaction_id_generator.dart'; import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; class ManagerForPeripheralMock extends Mock implements ManagerForPeripheral {} class ServiceMock extends Mock implements Service {} class CharacteristicMock extends Mock implements Characteristic {} +class TransactionIdGeneratorMock extends Mock implements TransactionIdGenerator {} void main() { const PERIPHERAL_NAME = 'Peripheral name'; const PERIPHERAL_ID = 'peripheral id'; - ManagerForPeripheralMock managerForPeripheral = ManagerForPeripheralMock(); + ManagerForPeripheralMock managerForPeripheral; + TransactionIdGeneratorMock transactionIdGeneratorMock; Peripheral peripheral; setUp(() { @@ -22,7 +25,9 @@ void main() { 'name': PERIPHERAL_NAME, 'id' : PERIPHERAL_ID }; - peripheral = Peripheral.fromJson(json, managerForPeripheral); + managerForPeripheral = ManagerForPeripheralMock(); + transactionIdGeneratorMock = TransactionIdGeneratorMock(); + peripheral = Peripheral.fromJson(json, managerForPeripheral, transactionIdGenerator: transactionIdGeneratorMock); }); group("Connect", () { @@ -126,13 +131,17 @@ void main() { }); test("use generated transactionId", () async { + //given + var ids = ["1", "5"]; + when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + //when await peripheral.discoverAllServicesAndCharacteristics(); await peripheral.discoverAllServicesAndCharacteristics(); //then verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, '1')); - verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, '2')); + verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, '5')); }); }); @@ -181,13 +190,17 @@ void main() { }); test("use generated transactionId", () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + //when await peripheral.rssi(); await peripheral.rssi(); //then - verify(managerForPeripheral.rssi(any, '1')); - verify(managerForPeripheral.rssi(any, '2')); + verify(managerForPeripheral.rssi(any, '4')); + verify(managerForPeripheral.rssi(any, '9')); }); }); diff --git a/test/src/util/transcation_id_generator_test.dart b/test/src/util/transcation_id_generator_test.dart index efa66cd9..ba71a030 100644 --- a/test/src/util/transcation_id_generator_test.dart +++ b/test/src/util/transcation_id_generator_test.dart @@ -2,14 +2,17 @@ import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_ble_lib/src/util/_transaction_id_generator.dart'; void main() { + + TransactionIdGenerator transactionIdGenerator = TransactionIdGenerator(); + test("should be able to generate an id", () { - expect(TransactionIdGenerator.getNextId(), isNotNull); + expect(transactionIdGenerator.getNextId(), isNotNull); }); test("should always return unique values", () { List generatedIds = []; for (var i = 0; i < 1000; i++) { - var generatedId = TransactionIdGenerator.getNextId(); + var generatedId = transactionIdGenerator.getNextId(); expect(generatedIds, isNot(contains(generatedId))); generatedIds.add(generatedId); } From e94fde587ff7f67be364051584f35b159c7ca42e Mon Sep 17 00:00:00 2001 From: pawelByszewski Date: Thu, 5 Mar 2020 13:28:33 +0100 Subject: [PATCH 5/7] tests for peripheral --- lib/src/_managers_for_classes.dart | 2 +- lib/src/internal_ble_manager.dart | 2 +- test/peripheral_test.dart | 228 ++++++++++++++++++++++++++++- 3 files changed, 223 insertions(+), 9 deletions(-) diff --git a/lib/src/_managers_for_classes.dart b/lib/src/_managers_for_classes.dart index 69a92814..ee1173d8 100644 --- a/lib/src/_managers_for_classes.dart +++ b/lib/src/_managers_for_classes.dart @@ -39,7 +39,7 @@ abstract class ManagerForPeripheral { String transactionId, ); - Future requestMtu( + Future requestMtu( Peripheral peripheral, int mtu, String transactionId, diff --git a/lib/src/internal_ble_manager.dart b/lib/src/internal_ble_manager.dart index 337490db..1265c714 100644 --- a/lib/src/internal_ble_manager.dart +++ b/lib/src/internal_ble_manager.dart @@ -174,7 +174,7 @@ class InternalBleManager } @override - Future requestMtu( + Future requestMtu( Peripheral peripheral, int mtu, String transactionId) { return _bleLib.requestMtu(peripheral, mtu, transactionId); } diff --git a/test/peripheral_test.dart b/test/peripheral_test.dart index 0fa0751f..649b8a06 100644 --- a/test/peripheral_test.dart +++ b/test/peripheral_test.dart @@ -1,5 +1,6 @@ -import 'package:flutter/services.dart'; +import 'dart:typed_data'; + import 'package:flutter_ble_lib/flutter_ble_lib.dart'; import 'package:flutter_ble_lib/src/_managers_for_classes.dart'; import 'package:flutter_ble_lib/src/util/_transaction_id_generator.dart'; @@ -10,6 +11,9 @@ class ManagerForPeripheralMock extends Mock implements ManagerForPeripheral {} class ServiceMock extends Mock implements Service {} class CharacteristicMock extends Mock implements Characteristic {} class TransactionIdGeneratorMock extends Mock implements TransactionIdGenerator {} +class CharacteristicWithValueMock extends Mock implements CharacteristicWithValue {} +class DescriptorMock extends Mock implements Descriptor {} +class DescriptorWithValueMock extends Mock implements DescriptorWithValue {} void main() { @@ -30,7 +34,7 @@ void main() { peripheral = Peripheral.fromJson(json, managerForPeripheral, transactionIdGenerator: transactionIdGeneratorMock); }); - group("Connect", () { + group("Connection", () { test('should pass defaut values to manager', () { //when peripheral.connect(); @@ -69,9 +73,7 @@ void main() { timeout: timeout )); }); - }); - group("Observe connection state", () { test("should emit on every connection state change", () { //given var states = [ @@ -89,7 +91,7 @@ void main() { expect(connectionStateStream, emitsInOrder(states)); }); - test("should pass arguments to manager", () { + test("should pass arguments to manager for observing connection state", () { //given var emitCurrentValue = true; var completeOnDisconnect = true; @@ -100,9 +102,15 @@ void main() { //then verify(managerForPeripheral.observePeripheralConnectionState(PERIPHERAL_ID, emitCurrentValue, completeOnDisconnect)); }); - }); - group("Connection checking", () { + test('should call disconnect on manager with valid arguments', () { + //when + peripheral.disconnectOrCancelConnection(); + + //then + verify(managerForPeripheral.disconnectOrCancelPeripheralConnection(PERIPHERAL_ID)); + }); + [true, false].forEach((isConnected) { test("returns isConneted information based on $isConnected returned by manager", () async { //given @@ -172,6 +180,102 @@ void main() { //then expect(fetchedCharacteristic, characteristics); }); + + test("schould return value of characteristic", () async { + //given + CharacteristicWithValue mockedCharacteristicWithValue = CharacteristicWithValueMock(); + var transactionId = "t1"; + when(managerForPeripheral.readCharacteristicForDevice(any, any, any, transactionId)) + .thenAnswer((_) => Future.value(mockedCharacteristicWithValue)); + + //when + CharacteristicWithValue characteristicWithValue = await peripheral.readCharacteristic('s1', 'c1', transactionId: transactionId); + + //then + expect(characteristicWithValue, mockedCharacteristicWithValue); + }); + + test("should use autogenerated transactionId during reading operation", () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.readCharacteristic('s1', 'c1'); + await peripheral.readCharacteristic('s1', 'c1'); + + //then + verify(managerForPeripheral.readCharacteristicForDevice(any, any, any, '4')); + verify(managerForPeripheral.readCharacteristicForDevice(any, any, any, '9')); + }); + + test("should write value to characteristic", () async { + //given + CharacteristicWithValue mockedCharacteristicWithValue = CharacteristicWithValueMock(); + const serviceUuid = 's1'; + const characteristicUuid = 'c1'; + const transactionId = 't1'; + Uint8List value = Uint8List.fromList([1, 4, 9]); + const withResponse = false; + + when(managerForPeripheral.writeCharacteristicForDevice(any, serviceUuid, characteristicUuid, value, withResponse, transactionId)) + .thenAnswer((_) => Future.value(mockedCharacteristicWithValue)); + + //when + CharacteristicWithValue characteristicWithValue = await peripheral.writeCharacteristic(serviceUuid, characteristicUuid, value, withResponse, transactionId: transactionId); + + //then + expect(characteristicWithValue, mockedCharacteristicWithValue); + }); + + test("should use autogenerated transactionId during writing operation", () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.writeCharacteristic('s1', 'c1', Uint8List.fromList([1]), false); + await peripheral.writeCharacteristic('s1', 'c1', Uint8List.fromList([1]), false); + + //then + verify(managerForPeripheral.writeCharacteristicForDevice(any, any, any, any, any, '4')); + verify(managerForPeripheral.writeCharacteristicForDevice(any, any, any, any, any, '9')); + }); + + test("should return values of monitored characteristic", () { + //given + var emittedValues = [ + CharacteristicWithValueMock(), + CharacteristicWithValueMock(), + CharacteristicWithValueMock() + ]; + const serviceUuid = 's1'; + const characteristicUuid = 'c1'; + const transactionId = 't1'; + when(managerForPeripheral.monitorCharacteristicForDevice(any, serviceUuid, characteristicUuid, transactionId)) + .thenAnswer((_) => Stream.fromIterable(emittedValues)); + + //when + Stream characteristicsStream = peripheral.monitorCharacteristic(serviceUuid, characteristicUuid, transactionId: transactionId); + + //then + expect(characteristicsStream, emitsInOrder(emittedValues)); + }); + + test("should use autogenerated transactionId for monitoring operation", () { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + + //when + peripheral.monitorCharacteristic('s1', 'c1'); + peripheral.monitorCharacteristic('s1', 'c1'); + + //then + verify(managerForPeripheral.monitorCharacteristicForDevice(any, any, any, '4')); + verify(managerForPeripheral.monitorCharacteristicForDevice(any, any, any, '9')); + }); + }); group("Rssi", () { @@ -204,4 +308,114 @@ void main() { }); }); + group("MTU", () { + test("returns negotiated MTU", () async { + //given + const requestedMtu = 23; + const negotiatedMtu = 135; + when(managerForPeripheral.requestMtu(any, requestedMtu, any)).thenAnswer((_) => Future.value(negotiatedMtu)); + + //when + int obtainedMtu = await peripheral.requestMtu(requestedMtu); + + //then + expect(negotiatedMtu, obtainedMtu); + }); + + test("use generated transactionId", () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.requestMtu(23); + await peripheral.requestMtu(45); + + //then + verify(managerForPeripheral.requestMtu(any, any, '4')); + verify(managerForPeripheral.requestMtu(any, any, '9')); + }); + }); + + group("Descriptor", () { + test("should return desriptors of characteristic", () async { + //given + List descriptors = [DescriptorMock(), DescriptorMock()]; + const serviceUuid = "123uuid"; + const characteristicUuid = "c1"; + when(managerForPeripheral.descriptorsForPeripheral(any, serviceUuid, characteristicUuid)).thenAnswer((_) => Future.value(descriptors)); + + //when + List fetchedDescriptors = await peripheral.descriptorsForCharacteristic(serviceUuid, characteristicUuid); + + //then + expect(fetchedDescriptors, descriptors); + }); + + test("should return Descriptor value", () async { + //given + DescriptorWithValue descriptorWithValue = DescriptorWithValueMock(); + const serviceUuid = "123uuid"; + const characteristicUuid = "c1"; + const descriptorUuid = "c1"; + const transactionId = "t1"; + when(managerForPeripheral.readDescriptorForPeripheral(any, serviceUuid, characteristicUuid, descriptorUuid, transactionId)) + .thenAnswer((_) => Future.value(descriptorWithValue)); + + //when + DescriptorWithValueMock obtainedDescriptorWithValue = await peripheral.readDescriptor(serviceUuid, characteristicUuid, descriptorUuid, transactionId: transactionId); + + //then + expect(obtainedDescriptorWithValue, descriptorWithValue); + }); + + test("should use autogenerated transactionId during reading operation", () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.readDescriptor('s1', 'c1', 'd1'); + await peripheral.readDescriptor('s1', 'c1', 'd1'); + + //then + verify(managerForPeripheral.readDescriptorForPeripheral(any, any, any, any, '4')); + verify(managerForPeripheral.readDescriptorForPeripheral(any, any, any, any, '9')); + }); + + test("should write value to descriptor", () async { + //given + DescriptorWithValue descriptorWithValue = DescriptorWithValueMock(); + const serviceUuid = "123uuid"; + const characteristicUuid = "c1"; + const descriptorUuid = "c1"; + const transactionId = "t1"; + Uint8List value = Uint8List.fromList([1, 4, 9]); + + when(managerForPeripheral.writeDescriptorForPeripheral(any, serviceUuid, characteristicUuid, descriptorUuid, value, transactionId)) + .thenAnswer((_) => Future.value(descriptorWithValue)); + + //when + DescriptorWithValue obtainedDescriptorWithValue = await peripheral.writeDescriptor(serviceUuid, characteristicUuid, descriptorUuid, value, transactionId: transactionId); + + //then + expect(obtainedDescriptorWithValue, descriptorWithValue); + }); + + test("should use autogenerated transactionId during writing operation", () async { + //given + var ids = ["4", "9"]; + when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + + //when + await peripheral.writeDescriptor('s1', 'c1', 'd1', Uint8List.fromList([1])); + await peripheral.writeDescriptor('s1', 'c1', 'd1', Uint8List.fromList([1])); + + //then + verify(managerForPeripheral.writeDescriptorForPeripheral(any, any, any, any, any, '4')); + verify(managerForPeripheral.writeDescriptorForPeripheral(any, any, any, any, any, '9')); + }); + }); + + } \ No newline at end of file From 20c81260d9aee60f9ed5b6a03e8de9cd19bdb0aa Mon Sep 17 00:00:00 2001 From: pawelByszewski Date: Thu, 5 Mar 2020 14:26:33 +0100 Subject: [PATCH 6/7] refactor --- test/peripheral_test.dart | 52 ++++++++++++++------------------------- 1 file changed, 19 insertions(+), 33 deletions(-) diff --git a/test/peripheral_test.dart b/test/peripheral_test.dart index 649b8a06..94523d7a 100644 --- a/test/peripheral_test.dart +++ b/test/peripheral_test.dart @@ -19,6 +19,11 @@ void main() { const PERIPHERAL_NAME = 'Peripheral name'; const PERIPHERAL_ID = 'peripheral id'; + const SERVICE_UUID = 's1'; + const CHARACTERISTIC_UUID = 'c1'; + const TRANSACTION_ID = 't1'; + const DESCRIPTOR_UUID = "d1"; + ManagerForPeripheralMock managerForPeripheral; TransactionIdGeneratorMock transactionIdGeneratorMock; @@ -128,14 +133,11 @@ void main() { group("Discovery", () { test("use given transactionId", () async { - //given - const transactionId = "86791384-"; - //when - await peripheral.discoverAllServicesAndCharacteristics(transactionId: transactionId); + await peripheral.discoverAllServicesAndCharacteristics(transactionId: TRANSACTION_ID); //then - verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, transactionId)); + verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, TRANSACTION_ID)); }); test("use generated transactionId", () async { @@ -171,11 +173,10 @@ void main() { test("should return characteristic for given service", () async { //given List characteristics = [CharacteristicMock(), CharacteristicMock()]; - const serviceUuid = "123uuid"; - when(managerForPeripheral.characteristics(any, serviceUuid)).thenAnswer((_) => Future.value(characteristics)); + when(managerForPeripheral.characteristics(any, SERVICE_UUID)).thenAnswer((_) => Future.value(characteristics)); //when - List fetchedCharacteristic = await peripheral.characteristics(serviceUuid); + List fetchedCharacteristic = await peripheral.characteristics(SERVICE_UUID); //then expect(fetchedCharacteristic, characteristics); @@ -212,17 +213,14 @@ void main() { test("should write value to characteristic", () async { //given CharacteristicWithValue mockedCharacteristicWithValue = CharacteristicWithValueMock(); - const serviceUuid = 's1'; - const characteristicUuid = 'c1'; - const transactionId = 't1'; Uint8List value = Uint8List.fromList([1, 4, 9]); const withResponse = false; - when(managerForPeripheral.writeCharacteristicForDevice(any, serviceUuid, characteristicUuid, value, withResponse, transactionId)) + when(managerForPeripheral.writeCharacteristicForDevice(any, SERVICE_UUID, CHARACTERISTIC_UUID, value, withResponse, TRANSACTION_ID)) .thenAnswer((_) => Future.value(mockedCharacteristicWithValue)); //when - CharacteristicWithValue characteristicWithValue = await peripheral.writeCharacteristic(serviceUuid, characteristicUuid, value, withResponse, transactionId: transactionId); + CharacteristicWithValue characteristicWithValue = await peripheral.writeCharacteristic(SERVICE_UUID, CHARACTERISTIC_UUID, value, withResponse, transactionId: TRANSACTION_ID); //then expect(characteristicWithValue, mockedCharacteristicWithValue); @@ -249,14 +247,11 @@ void main() { CharacteristicWithValueMock(), CharacteristicWithValueMock() ]; - const serviceUuid = 's1'; - const characteristicUuid = 'c1'; - const transactionId = 't1'; - when(managerForPeripheral.monitorCharacteristicForDevice(any, serviceUuid, characteristicUuid, transactionId)) + when(managerForPeripheral.monitorCharacteristicForDevice(any, SERVICE_UUID, CHARACTERISTIC_UUID, TRANSACTION_ID)) .thenAnswer((_) => Stream.fromIterable(emittedValues)); //when - Stream characteristicsStream = peripheral.monitorCharacteristic(serviceUuid, characteristicUuid, transactionId: transactionId); + Stream characteristicsStream = peripheral.monitorCharacteristic(SERVICE_UUID, CHARACTERISTIC_UUID, transactionId: TRANSACTION_ID); //then expect(characteristicsStream, emitsInOrder(emittedValues)); @@ -341,12 +336,10 @@ void main() { test("should return desriptors of characteristic", () async { //given List descriptors = [DescriptorMock(), DescriptorMock()]; - const serviceUuid = "123uuid"; - const characteristicUuid = "c1"; - when(managerForPeripheral.descriptorsForPeripheral(any, serviceUuid, characteristicUuid)).thenAnswer((_) => Future.value(descriptors)); + when(managerForPeripheral.descriptorsForPeripheral(any, SERVICE_UUID, CHARACTERISTIC_UUID)).thenAnswer((_) => Future.value(descriptors)); //when - List fetchedDescriptors = await peripheral.descriptorsForCharacteristic(serviceUuid, characteristicUuid); + List fetchedDescriptors = await peripheral.descriptorsForCharacteristic(SERVICE_UUID, CHARACTERISTIC_UUID); //then expect(fetchedDescriptors, descriptors); @@ -355,15 +348,12 @@ void main() { test("should return Descriptor value", () async { //given DescriptorWithValue descriptorWithValue = DescriptorWithValueMock(); - const serviceUuid = "123uuid"; - const characteristicUuid = "c1"; - const descriptorUuid = "c1"; const transactionId = "t1"; - when(managerForPeripheral.readDescriptorForPeripheral(any, serviceUuid, characteristicUuid, descriptorUuid, transactionId)) + when(managerForPeripheral.readDescriptorForPeripheral(any, SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, transactionId)) .thenAnswer((_) => Future.value(descriptorWithValue)); //when - DescriptorWithValueMock obtainedDescriptorWithValue = await peripheral.readDescriptor(serviceUuid, characteristicUuid, descriptorUuid, transactionId: transactionId); + DescriptorWithValueMock obtainedDescriptorWithValue = await peripheral.readDescriptor(SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, transactionId: transactionId); //then expect(obtainedDescriptorWithValue, descriptorWithValue); @@ -386,17 +376,13 @@ void main() { test("should write value to descriptor", () async { //given DescriptorWithValue descriptorWithValue = DescriptorWithValueMock(); - const serviceUuid = "123uuid"; - const characteristicUuid = "c1"; - const descriptorUuid = "c1"; - const transactionId = "t1"; Uint8List value = Uint8List.fromList([1, 4, 9]); - when(managerForPeripheral.writeDescriptorForPeripheral(any, serviceUuid, characteristicUuid, descriptorUuid, value, transactionId)) + when(managerForPeripheral.writeDescriptorForPeripheral(any, SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, value, TRANSACTION_ID)) .thenAnswer((_) => Future.value(descriptorWithValue)); //when - DescriptorWithValue obtainedDescriptorWithValue = await peripheral.writeDescriptor(serviceUuid, characteristicUuid, descriptorUuid, value, transactionId: transactionId); + DescriptorWithValue obtainedDescriptorWithValue = await peripheral.writeDescriptor(SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, value, transactionId: TRANSACTION_ID); //then expect(obtainedDescriptorWithValue, descriptorWithValue); From 76a172e0fea8ce7185edeaa39d5a2be81975e14b Mon Sep 17 00:00:00 2001 From: pawelByszewski Date: Thu, 5 Mar 2020 15:55:52 +0100 Subject: [PATCH 7/7] fixes after review --- Flutter User Facing API.dart | 3 +- lib/characteristic.dart | 10 +- lib/descriptor.dart | 25 +- lib/peripheral.dart | 4 +- lib/service.dart | 11 +- lib/src/internal_ble_manager.dart | 2 +- lib/src/util/_transaction_id_generator.dart | 8 +- test/peripheral_test.dart | 250 +++++++++++------- .../util/transcation_id_generator_test.dart | 6 +- 9 files changed, 193 insertions(+), 126 deletions(-) diff --git a/Flutter User Facing API.dart b/Flutter User Facing API.dart index 579572ed..03f509f2 100644 --- a/Flutter User Facing API.dart +++ b/Flutter User Facing API.dart @@ -10,7 +10,8 @@ abstract class BluetoothLowEnergyManager { Future enableRadio(); Future disableRadio(); - Future cancelTransaction(String transactionId); + Future cancelTransaction(String const transactionId = "t1"; +); Future setLogLevel(LogLevel logLevel); Future logLevel(); diff --git a/lib/characteristic.dart b/lib/characteristic.dart index fe87c5be..68ab0201 100644 --- a/lib/characteristic.dart +++ b/lib/characteristic.dart @@ -41,9 +41,13 @@ class Characteristic extends InternalCharacteristic { /// True if this characteristic can be monitored via indications. bool isIndicatable; - Characteristic.fromJson(Map jsonObject, Service service, - ManagerForCharacteristic manager, {TransactionIdGenerator transactionIdGenerator = const TransactionIdGenerator()}) - : super(jsonObject[_CharacteristicMetadata.id]) { + Characteristic.fromJson( + Map jsonObject, + Service service, + ManagerForCharacteristic manager, { + TransactionIdGenerator transactionIdGenerator = + TransactionIdGenerator.INSTANCE, + }) : super(jsonObject[_CharacteristicMetadata.id]) { _manager = manager; _transactionIdGenerator = transactionIdGenerator; this.service = service; diff --git a/lib/descriptor.dart b/lib/descriptor.dart index 427cea19..d44d6065 100644 --- a/lib/descriptor.dart +++ b/lib/descriptor.dart @@ -12,12 +12,11 @@ class Descriptor extends InternalDescriptor { Characteristic characteristic; String uuid; - Descriptor.fromJson( - Map jsonObject, - Characteristic characteristic, - ManagerForDescriptor manager, - {TransactionIdGenerator transactionIdGenerator = const TransactionIdGenerator()} - ) : super(jsonObject[_DescriptorMetadata.id]) { + Descriptor.fromJson(Map jsonObject, + Characteristic characteristic, ManagerForDescriptor manager, + {TransactionIdGenerator transactionIdGenerator = + TransactionIdGenerator.INSTANCE}) + : super(jsonObject[_DescriptorMetadata.id]) { _manager = manager; _transactionIdGenerator = transactionIdGenerator; this.characteristic = characteristic; @@ -40,17 +39,15 @@ class Descriptor extends InternalDescriptor { @override bool operator ==(Object other) => identical(this, other) || - other is Descriptor && - runtimeType == other.runtimeType && - _manager == other._manager && - characteristic == other.characteristic && - uuid == other.uuid; + other is Descriptor && + runtimeType == other.runtimeType && + _manager == other._manager && + characteristic == other.characteristic && + uuid == other.uuid; @override int get hashCode => - _manager.hashCode ^ - characteristic.hashCode ^ - uuid.hashCode; + _manager.hashCode ^ characteristic.hashCode ^ uuid.hashCode; } class DescriptorWithValue extends Descriptor with WithValue { diff --git a/lib/peripheral.dart b/lib/peripheral.dart index 70251472..e785eb22 100644 --- a/lib/peripheral.dart +++ b/lib/peripheral.dart @@ -21,7 +21,9 @@ class Peripheral { String name; String identifier; - Peripheral.fromJson(Map json, ManagerForPeripheral manager, {TransactionIdGenerator transactionIdGenerator = const TransactionIdGenerator()}) + Peripheral.fromJson(Map json, ManagerForPeripheral manager, + {TransactionIdGenerator transactionIdGenerator = + TransactionIdGenerator.INSTANCE}) : _manager = manager, name = json[_PeripheralMetadata.name], identifier = json[_PeripheralMetadata.identifier], diff --git a/lib/service.dart b/lib/service.dart index 5c59d3c1..064a45a6 100644 --- a/lib/service.dart +++ b/lib/service.dart @@ -16,12 +16,11 @@ class Service extends InternalService { /// The UUID of this service. String uuid; - Service.fromJson( - Map jsonObject, - Peripheral peripheral, - ManagerForService managerForService, - {TransactionIdGenerator transactionIdGenerator = const TransactionIdGenerator()} - ) : super(jsonObject[_ServiceMetadata.id]) { + Service.fromJson(Map jsonObject, Peripheral peripheral, + ManagerForService managerForService, + {TransactionIdGenerator transactionIdGenerator = + TransactionIdGenerator.INSTANCE}) + : super(jsonObject[_ServiceMetadata.id]) { this.peripheral = peripheral; uuid = jsonObject[_ServiceMetadata.uuid]; _manager = managerForService; diff --git a/lib/src/internal_ble_manager.dart b/lib/src/internal_ble_manager.dart index 1265c714..6e30c396 100644 --- a/lib/src/internal_ble_manager.dart +++ b/lib/src/internal_ble_manager.dart @@ -10,7 +10,7 @@ class InternalBleManager FlutterBleLib _bleLib; TransactionIdGenerator _transactionIdGenerator; - InternalBleManager({TransactionIdGenerator transactionIdGenerator = const TransactionIdGenerator()}) { + InternalBleManager({TransactionIdGenerator transactionIdGenerator = TransactionIdGenerator.INSTANCE}) { _bleLib = FlutterBleLib(); _bleLib.registerManager(this); _transactionIdGenerator = transactionIdGenerator; diff --git a/lib/src/util/_transaction_id_generator.dart b/lib/src/util/_transaction_id_generator.dart index 4ab7efd1..5b7be416 100644 --- a/lib/src/util/_transaction_id_generator.dart +++ b/lib/src/util/_transaction_id_generator.dart @@ -1,11 +1,13 @@ class TransactionIdGenerator { static int _id = 0; - - - const TransactionIdGenerator(); + static const TransactionIdGenerator INSTANCE = const TransactionIdGenerator._internal(); String getNextId() { _id++; return _id.toString(); } + + const TransactionIdGenerator._internal(); } + + diff --git a/test/peripheral_test.dart b/test/peripheral_test.dart index 94523d7a..e5ce2c73 100644 --- a/test/peripheral_test.dart +++ b/test/peripheral_test.dart @@ -1,4 +1,3 @@ - import 'dart:typed_data'; import 'package:flutter_ble_lib/flutter_ble_lib.dart'; @@ -8,15 +7,22 @@ import 'package:mockito/mockito.dart'; import 'package:test/test.dart'; class ManagerForPeripheralMock extends Mock implements ManagerForPeripheral {} + class ServiceMock extends Mock implements Service {} + class CharacteristicMock extends Mock implements Characteristic {} -class TransactionIdGeneratorMock extends Mock implements TransactionIdGenerator {} -class CharacteristicWithValueMock extends Mock implements CharacteristicWithValue {} + +class TransactionIdGeneratorMock extends Mock + implements TransactionIdGenerator {} + +class CharacteristicWithValueMock extends Mock + implements CharacteristicWithValue {} + class DescriptorMock extends Mock implements Descriptor {} + class DescriptorWithValueMock extends Mock implements DescriptorWithValue {} void main() { - const PERIPHERAL_NAME = 'Peripheral name'; const PERIPHERAL_ID = 'peripheral id'; const SERVICE_UUID = 's1'; @@ -24,19 +30,16 @@ void main() { const TRANSACTION_ID = 't1'; const DESCRIPTOR_UUID = "d1"; - ManagerForPeripheralMock managerForPeripheral; TransactionIdGeneratorMock transactionIdGeneratorMock; Peripheral peripheral; setUp(() { - Map json = { - 'name': PERIPHERAL_NAME, - 'id' : PERIPHERAL_ID - }; + Map json = {'name': PERIPHERAL_NAME, 'id': PERIPHERAL_ID}; managerForPeripheral = ManagerForPeripheralMock(); transactionIdGeneratorMock = TransactionIdGeneratorMock(); - peripheral = Peripheral.fromJson(json, managerForPeripheral, transactionIdGenerator: transactionIdGeneratorMock); + peripheral = Peripheral.fromJson(json, managerForPeripheral, + transactionIdGenerator: transactionIdGeneratorMock); }); group("Connection", () { @@ -45,13 +48,11 @@ void main() { peripheral.connect(); //then - verify(managerForPeripheral.connectToPeripheral( - PERIPHERAL_ID, + verify(managerForPeripheral.connectToPeripheral(PERIPHERAL_ID, isAutoConnect: false, requestMtu: 0, refreshGatt: false, - timeout: null - )); + timeout: null)); }); test('should pass given values to manager', () { @@ -63,20 +64,17 @@ void main() { //when peripheral.connect( - isAutoConnect: isAutoConnect, - requestMtu: mtu, - refreshGatt: refreshGatt, - timeout: timeout - ); + isAutoConnect: isAutoConnect, + requestMtu: mtu, + refreshGatt: refreshGatt, + timeout: timeout); //then - verify(managerForPeripheral.connectToPeripheral( - PERIPHERAL_ID, + verify(managerForPeripheral.connectToPeripheral(PERIPHERAL_ID, isAutoConnect: isAutoConnect, requestMtu: mtu, refreshGatt: refreshGatt, - timeout: timeout - )); + timeout: timeout)); }); test("should emit on every connection state change", () { @@ -90,7 +88,8 @@ void main() { .thenAnswer((_) => Stream.fromIterable(states)); //when - Stream connectionStateStream = peripheral.observeConnectionState(); + Stream connectionStateStream = + peripheral.observeConnectionState(); //then expect(connectionStateStream, emitsInOrder(states)); @@ -102,10 +101,13 @@ void main() { var completeOnDisconnect = true; //when - peripheral.observeConnectionState(emitCurrentValue: emitCurrentValue, completeOnDisconnect: completeOnDisconnect); + peripheral.observeConnectionState( + emitCurrentValue: emitCurrentValue, + completeOnDisconnect: completeOnDisconnect); //then - verify(managerForPeripheral.observePeripheralConnectionState(PERIPHERAL_ID, emitCurrentValue, completeOnDisconnect)); + verify(managerForPeripheral.observePeripheralConnectionState( + PERIPHERAL_ID, emitCurrentValue, completeOnDisconnect)); }); test('should call disconnect on manager with valid arguments', () { @@ -113,11 +115,14 @@ void main() { peripheral.disconnectOrCancelConnection(); //then - verify(managerForPeripheral.disconnectOrCancelPeripheralConnection(PERIPHERAL_ID)); + verify(managerForPeripheral + .disconnectOrCancelPeripheralConnection(PERIPHERAL_ID)); }); [true, false].forEach((isConnected) { - test("returns isConneted information based on $isConnected returned by manager", () async { + test( + "returns isConneted information based on $isConnected returned by manager", + () async { //given when(managerForPeripheral.isPeripheralConnected(any)) .thenAnswer((_) => Future.value(isConnected)); @@ -134,24 +139,29 @@ void main() { group("Discovery", () { test("use given transactionId", () async { //when - await peripheral.discoverAllServicesAndCharacteristics(transactionId: TRANSACTION_ID); + await peripheral.discoverAllServicesAndCharacteristics( + transactionId: TRANSACTION_ID); //then - verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, TRANSACTION_ID)); + verify(managerForPeripheral.discoverAllServicesAndCharacteristics( + any, TRANSACTION_ID)); }); test("use generated transactionId", () async { //given var ids = ["1", "5"]; - when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); //when await peripheral.discoverAllServicesAndCharacteristics(); await peripheral.discoverAllServicesAndCharacteristics(); //then - verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, '1')); - verify(managerForPeripheral.discoverAllServicesAndCharacteristics(any, '5')); + verify( + managerForPeripheral.discoverAllServicesAndCharacteristics(any, '1')); + verify( + managerForPeripheral.discoverAllServicesAndCharacteristics(any, '5')); }); }); @@ -159,7 +169,8 @@ void main() { test("should return services", () async { //given List services = [ServiceMock(), ServiceMock()]; - when(managerForPeripheral.services(any)).thenAnswer((_) => Future.value(services)); + when(managerForPeripheral.services(any)) + .thenAnswer((_) => Future.value(services)); //when List fetchedServices = await peripheral.services(); @@ -172,72 +183,94 @@ void main() { group("Characteristics", () { test("should return characteristic for given service", () async { //given - List characteristics = [CharacteristicMock(), CharacteristicMock()]; - when(managerForPeripheral.characteristics(any, SERVICE_UUID)).thenAnswer((_) => Future.value(characteristics)); + List characteristics = [ + CharacteristicMock(), + CharacteristicMock() + ]; + when(managerForPeripheral.characteristics(any, SERVICE_UUID)) + .thenAnswer((_) => Future.value(characteristics)); //when - List fetchedCharacteristic = await peripheral.characteristics(SERVICE_UUID); + List fetchedCharacteristic = + await peripheral.characteristics(SERVICE_UUID); //then expect(fetchedCharacteristic, characteristics); }); - test("schould return value of characteristic", () async { + test("should return value of characteristic", () async { //given - CharacteristicWithValue mockedCharacteristicWithValue = CharacteristicWithValueMock(); - var transactionId = "t1"; - when(managerForPeripheral.readCharacteristicForDevice(any, any, any, transactionId)) - .thenAnswer((_) => Future.value(mockedCharacteristicWithValue)); + CharacteristicWithValue mockedCharacteristicWithValue = + CharacteristicWithValueMock(); + when(managerForPeripheral.readCharacteristicForDevice( + any, any, any, TRANSACTION_ID)) + .thenAnswer((_) => Future.value(mockedCharacteristicWithValue)); //when - CharacteristicWithValue characteristicWithValue = await peripheral.readCharacteristic('s1', 'c1', transactionId: transactionId); + CharacteristicWithValue characteristicWithValue = await peripheral + .readCharacteristic('s1', 'c1', transactionId: TRANSACTION_ID); //then expect(characteristicWithValue, mockedCharacteristicWithValue); }); - test("should use autogenerated transactionId during reading operation", () async { + test("should use autogenerated transactionId during reading operation", + () async { //given var ids = ["4", "9"]; - when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); //when await peripheral.readCharacteristic('s1', 'c1'); await peripheral.readCharacteristic('s1', 'c1'); //then - verify(managerForPeripheral.readCharacteristicForDevice(any, any, any, '4')); - verify(managerForPeripheral.readCharacteristicForDevice(any, any, any, '9')); + verify( + managerForPeripheral.readCharacteristicForDevice(any, any, any, '4')); + verify( + managerForPeripheral.readCharacteristicForDevice(any, any, any, '9')); }); test("should write value to characteristic", () async { //given - CharacteristicWithValue mockedCharacteristicWithValue = CharacteristicWithValueMock(); + CharacteristicWithValue mockedCharacteristicWithValue = + CharacteristicWithValueMock(); Uint8List value = Uint8List.fromList([1, 4, 9]); const withResponse = false; - when(managerForPeripheral.writeCharacteristicForDevice(any, SERVICE_UUID, CHARACTERISTIC_UUID, value, withResponse, TRANSACTION_ID)) + when(managerForPeripheral.writeCharacteristicForDevice(any, SERVICE_UUID, + CHARACTERISTIC_UUID, value, withResponse, TRANSACTION_ID)) .thenAnswer((_) => Future.value(mockedCharacteristicWithValue)); //when - CharacteristicWithValue characteristicWithValue = await peripheral.writeCharacteristic(SERVICE_UUID, CHARACTERISTIC_UUID, value, withResponse, transactionId: TRANSACTION_ID); + CharacteristicWithValue characteristicWithValue = + await peripheral.writeCharacteristic( + SERVICE_UUID, CHARACTERISTIC_UUID, value, withResponse, + transactionId: TRANSACTION_ID); //then expect(characteristicWithValue, mockedCharacteristicWithValue); }); - test("should use autogenerated transactionId during writing operation", () async { + test("should use autogenerated transactionId during writing operation", + () async { //given var ids = ["4", "9"]; - when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); //when - await peripheral.writeCharacteristic('s1', 'c1', Uint8List.fromList([1]), false); - await peripheral.writeCharacteristic('s1', 'c1', Uint8List.fromList([1]), false); + await peripheral.writeCharacteristic( + 's1', 'c1', Uint8List.fromList([1]), false); + await peripheral.writeCharacteristic( + 's1', 'c1', Uint8List.fromList([1]), false); //then - verify(managerForPeripheral.writeCharacteristicForDevice(any, any, any, any, any, '4')); - verify(managerForPeripheral.writeCharacteristicForDevice(any, any, any, any, any, '9')); + verify(managerForPeripheral.writeCharacteristicForDevice( + any, any, any, any, any, '4')); + verify(managerForPeripheral.writeCharacteristicForDevice( + any, any, any, any, any, '9')); }); test("should return values of monitored characteristic", () { @@ -247,11 +280,14 @@ void main() { CharacteristicWithValueMock(), CharacteristicWithValueMock() ]; - when(managerForPeripheral.monitorCharacteristicForDevice(any, SERVICE_UUID, CHARACTERISTIC_UUID, TRANSACTION_ID)) + when(managerForPeripheral.monitorCharacteristicForDevice( + any, SERVICE_UUID, CHARACTERISTIC_UUID, TRANSACTION_ID)) .thenAnswer((_) => Stream.fromIterable(emittedValues)); //when - Stream characteristicsStream = peripheral.monitorCharacteristic(SERVICE_UUID, CHARACTERISTIC_UUID, transactionId: TRANSACTION_ID); + Stream characteristicsStream = + peripheral.monitorCharacteristic(SERVICE_UUID, CHARACTERISTIC_UUID, + transactionId: TRANSACTION_ID); //then expect(characteristicsStream, emitsInOrder(emittedValues)); @@ -260,38 +296,41 @@ void main() { test("should use autogenerated transactionId for monitoring operation", () { //given var ids = ["4", "9"]; - when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); //when - peripheral.monitorCharacteristic('s1', 'c1'); - peripheral.monitorCharacteristic('s1', 'c1'); + peripheral.monitorCharacteristic('s1', 'c1'); + peripheral.monitorCharacteristic('s1', 'c1'); //then - verify(managerForPeripheral.monitorCharacteristicForDevice(any, any, any, '4')); - verify(managerForPeripheral.monitorCharacteristicForDevice(any, any, any, '9')); + verify(managerForPeripheral.monitorCharacteristicForDevice( + any, any, any, '4')); + verify(managerForPeripheral.monitorCharacteristicForDevice( + any, any, any, '9')); }); - }); group("Rssi", () { test("use given transactionId", () async { //given - const transactionId = "86791384-"; - const rssi = 23; - when(managerForPeripheral.rssi(any, transactionId)).thenAnswer((_) => Future.value(rssi)); + const rssi = -23; + when(managerForPeripheral.rssi(any, TRANSACTION_ID)) + .thenAnswer((_) => Future.value(rssi)); //when - int obtainedRssi = await peripheral.rssi(transactionId: transactionId); + int obtainedRssi = await peripheral.rssi(transactionId: TRANSACTION_ID); //then - verify(managerForPeripheral.rssi(any, transactionId)); + verify(managerForPeripheral.rssi(any, TRANSACTION_ID)); expect(obtainedRssi, rssi); }); test("use generated transactionId", () async { //given var ids = ["4", "9"]; - when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); //when await peripheral.rssi(); @@ -306,9 +345,10 @@ void main() { group("MTU", () { test("returns negotiated MTU", () async { //given - const requestedMtu = 23; - const negotiatedMtu = 135; - when(managerForPeripheral.requestMtu(any, requestedMtu, any)).thenAnswer((_) => Future.value(negotiatedMtu)); + const requestedMtu = 100; + const negotiatedMtu = 50; + when(managerForPeripheral.requestMtu(any, requestedMtu, any)) + .thenAnswer((_) => Future.value(negotiatedMtu)); //when int obtainedMtu = await peripheral.requestMtu(requestedMtu); @@ -320,7 +360,8 @@ void main() { test("use generated transactionId", () async { //given var ids = ["4", "9"]; - when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); //when await peripheral.requestMtu(23); @@ -336,10 +377,13 @@ void main() { test("should return desriptors of characteristic", () async { //given List descriptors = [DescriptorMock(), DescriptorMock()]; - when(managerForPeripheral.descriptorsForPeripheral(any, SERVICE_UUID, CHARACTERISTIC_UUID)).thenAnswer((_) => Future.value(descriptors)); + when(managerForPeripheral.descriptorsForPeripheral( + any, SERVICE_UUID, CHARACTERISTIC_UUID)) + .thenAnswer((_) => Future.value(descriptors)); //when - List fetchedDescriptors = await peripheral.descriptorsForCharacteristic(SERVICE_UUID, CHARACTERISTIC_UUID); + List fetchedDescriptors = await peripheral + .descriptorsForCharacteristic(SERVICE_UUID, CHARACTERISTIC_UUID); //then expect(fetchedDescriptors, descriptors); @@ -347,61 +391,75 @@ void main() { test("should return Descriptor value", () async { //given - DescriptorWithValue descriptorWithValue = DescriptorWithValueMock(); - const transactionId = "t1"; - when(managerForPeripheral.readDescriptorForPeripheral(any, SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, transactionId)) + DescriptorWithValue descriptorWithValue = DescriptorWithValueMock(); + when(managerForPeripheral.readDescriptorForPeripheral(any, SERVICE_UUID, + CHARACTERISTIC_UUID, DESCRIPTOR_UUID, TRANSACTION_ID)) .thenAnswer((_) => Future.value(descriptorWithValue)); //when - DescriptorWithValueMock obtainedDescriptorWithValue = await peripheral.readDescriptor(SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, transactionId: transactionId); + DescriptorWithValueMock obtainedDescriptorWithValue = await peripheral + .readDescriptor(SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, + transactionId: TRANSACTION_ID); //then expect(obtainedDescriptorWithValue, descriptorWithValue); }); - test("should use autogenerated transactionId during reading operation", () async { + test("should use autogenerated transactionId during reading operation", + () async { //given var ids = ["4", "9"]; - when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); //when await peripheral.readDescriptor('s1', 'c1', 'd1'); await peripheral.readDescriptor('s1', 'c1', 'd1'); //then - verify(managerForPeripheral.readDescriptorForPeripheral(any, any, any, any, '4')); - verify(managerForPeripheral.readDescriptorForPeripheral(any, any, any, any, '9')); + verify(managerForPeripheral.readDescriptorForPeripheral( + any, any, any, any, '4')); + verify(managerForPeripheral.readDescriptorForPeripheral( + any, any, any, any, '9')); }); test("should write value to descriptor", () async { //given - DescriptorWithValue descriptorWithValue = DescriptorWithValueMock(); + DescriptorWithValue descriptorWithValue = DescriptorWithValueMock(); Uint8List value = Uint8List.fromList([1, 4, 9]); - when(managerForPeripheral.writeDescriptorForPeripheral(any, SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, value, TRANSACTION_ID)) + when(managerForPeripheral.writeDescriptorForPeripheral(any, SERVICE_UUID, + CHARACTERISTIC_UUID, DESCRIPTOR_UUID, value, TRANSACTION_ID)) .thenAnswer((_) => Future.value(descriptorWithValue)); //when - DescriptorWithValue obtainedDescriptorWithValue = await peripheral.writeDescriptor(SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, value, transactionId: TRANSACTION_ID); + DescriptorWithValue obtainedDescriptorWithValue = + await peripheral.writeDescriptor( + SERVICE_UUID, CHARACTERISTIC_UUID, DESCRIPTOR_UUID, value, + transactionId: TRANSACTION_ID); //then expect(obtainedDescriptorWithValue, descriptorWithValue); }); - test("should use autogenerated transactionId during writing operation", () async { + test("should use autogenerated transactionId during writing operation", + () async { //given var ids = ["4", "9"]; - when(transactionIdGeneratorMock.getNextId()).thenAnswer((_) => ids.removeAt(0)); + when(transactionIdGeneratorMock.getNextId()) + .thenAnswer((_) => ids.removeAt(0)); //when - await peripheral.writeDescriptor('s1', 'c1', 'd1', Uint8List.fromList([1])); - await peripheral.writeDescriptor('s1', 'c1', 'd1', Uint8List.fromList([1])); + await peripheral.writeDescriptor( + 's1', 'c1', 'd1', Uint8List.fromList([1])); + await peripheral.writeDescriptor( + 's1', 'c1', 'd1', Uint8List.fromList([1])); //then - verify(managerForPeripheral.writeDescriptorForPeripheral(any, any, any, any, any, '4')); - verify(managerForPeripheral.writeDescriptorForPeripheral(any, any, any, any, any, '9')); + verify(managerForPeripheral.writeDescriptorForPeripheral( + any, any, any, any, any, '4')); + verify(managerForPeripheral.writeDescriptorForPeripheral( + any, any, any, any, any, '9')); }); }); - - -} \ No newline at end of file +} diff --git a/test/src/util/transcation_id_generator_test.dart b/test/src/util/transcation_id_generator_test.dart index ba71a030..ac98eab2 100644 --- a/test/src/util/transcation_id_generator_test.dart +++ b/test/src/util/transcation_id_generator_test.dart @@ -3,7 +3,11 @@ import 'package:flutter_ble_lib/src/util/_transaction_id_generator.dart'; void main() { - TransactionIdGenerator transactionIdGenerator = TransactionIdGenerator(); + TransactionIdGenerator transactionIdGenerator; + + setUp((){ + transactionIdGenerator = TransactionIdGenerator.INSTANCE; + }); test("should be able to generate an id", () { expect(transactionIdGenerator.getNextId(), isNotNull);