c# - 测试 UWP 蓝牙应用程序

标签 c# windows unit-testing testing uwp

我正在尝试为使用 Windows.Devices.Bluetooth.BluetoothLEDevice 的 Windows 10 UWP 应用程序开发一些测试。我有一个普通类,它是我的应用程序的一部分,它有一个私有(private) BluetoothLEDevice 类型字段。

class MyDevice
{
    private Windows.Devices.Bluetooth.BluetoothLEDevice BluetoothLEDevice;

    public string SomeProperty { get; set; }

    public MyDevice(Windows.Devices.Bluetooth.BluetoothLEDevice bluetoothLEDevice)
    {
        BluetoothLEDevice = bluetoothLEDevice;

        var characteristic = BluetoothLEDevice.GetGattService(...)
            .GetCharacteristics(...)
            .First();

        characteristic.ValueChanged += OnValueChanged;
    } 

    // TODO: Write tests for this method
    private OnValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args)
    {
        string message = Encoding.ASCII.GetString(args.CharacteristicValue.ToArray());

        // Parse `message`

        SomeProperty = parsed;
    }

    ...
}

该类的方法使用bluetoothLEDevice的事件和方法,有些是私有(private)的,有些是公共(public)的。如何测试 MyDevice 的公共(public)方法?

我已经尝试过类似的东西,我认为可以工作,但我可以看到它需要数百行代码和相当多的额外类,因为我需要实现很多FakeBluetoothLEDevice 中的内容,以使其正常工作。

我更改了 MyDevice 以接受包装器,然后创建包装器的两个实现。一个用于测试,另一个用于实际使用。

class MyDevice
{
    private MyApp.IBluetoothLEDeviceWrapper bluetoothLEDevice;
}

然后在我的测试中我使用假的。

private void ValueChangedEventDataParsingTest()
{
    var device = new FakeBluetoothLEDevice();

    var myDevice = new MyDevice(device);

    device.InvokeValueChanged("this is the value for a fake ValueChangedEvent");

    Assert.Equals(probe.SomeProperty, "expected");
}

是否有任何框架(适用于 UWP)可以帮助我实现我想要的目标?或者更好的方法来减轻我的痛苦?

最佳答案

与其关注实现问题,不如关注您希望抽象公开的功能。使用您的简化示例,我能够通过一些重构来复制它,以便仅与所需的功能进行交互。

[TestClass]
public class DeviceTests {
    [TestMethod]
    public void _ValueChangedEventDataParsingTest() {
        //Arrange
        var message = "message";
        var expected = "expected";
        var device = new FakeBluetoothLEDevice(message, expected);
        var sut = new MyDevice(device);

        //Act
        device.InvokeValueChanged(message);

        //Assert
        Assert.AreEqual(expected, sut.SomeProperty);
    }

    public interface IBlueToothService {
        Action<string> ValueChangedHandler { get; set; }
    }

    public class FakeBluetoothLEDevice : IBlueToothService {
        private string message;
        private string parsed;

        public FakeBluetoothLEDevice(string message, string expected) {
            this.message = message;
            this.parsed = expected;
        }
        public Action<string> ValueChangedHandler { get; set; }

        public void InvokeValueChanged(string p) {
            var handler = ValueChangedHandler ?? delegate { };
            if (p == message) {
                ValueChangedHandler(parsed);
            }
        }
    }

    public class MyDevice {
        private IBlueToothService device;

        public string SomeProperty { get; set; }

        public MyDevice(IBlueToothService device) {
            this.device = device;
            device.ValueChangedHandler = handler;
        }

        private void handler(string parsedValue) {
            SomeProperty = parsedValue;
        }
    }
}

使用关注点分离,将繁重的实现关注点转移到实际实现背后。它极大地简化了此类功能的使用者。

如果关注点是测试他的解析功能,那么也将 out 抽象为它自己的关注点。不要让类(class)做超出他们需要的事情 (SRP)

private OnValueChanged(GattCharacteristic sender, GattValueChangedEventArgs args) {
    string message = Encoding.ASCII.GetString(args.CharacteristicValue.ToArray());

    // Parse `message`
    var parsed = parsingServce.Parse(message);

    SomeProperty = parsed;
}

这样,解析服务实现只需要针对 ts 核心功能进行测试。

但是从抽象的角度来看,在测试更高级别的功能时不需要解析器作为依赖项。

我建议审查当前的设计并重构它以使其更加可靠。

关于c# - 测试 UWP 蓝牙应用程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43126807/

相关文章:

c# - Unity3D : C# - Can't seem to handle single/double/hold touches correctly

c++ - 如何复制文件并继承Windows EFS?

java - @ReplaceWithMock 与 @Qualifier

c++ - win 7可以设置单步陷阱吗?

unit-testing - 使用 jest 和 vue-test-utils2 在 vue3 typescript 单元测试中模拟 axios (已解决)

c# - 从 dotnet 测试中排除命名空间

c# - 转换 List<T> 中的 IEnumerable

c# - 在代码隐藏中使用 XDocument 时出错

c# - 当我渲染局部 View 时,我的模型为空

c++ - 使用 C++ 异常时 Windows 上可能的最小堆栈大小(使用 boost 上下文纤维)