如何模拟 IotHubServiceClient 进行测试? (v2)

问题描述 投票:0回答:1

我有一个类

IotHubService
,它依赖于 C# IoTHub SDK 的
IotHubServiceClient
(SDK 的 v2 版本,当前处于预览版)来在 IoTHub 上执行各种查询。我试图通过编写一些测试和模拟依赖关系来提高班级的可靠性:

[Fact]
public async Task GetDeviceByIdAsync_ValidDeviceId_ReturnsDevice()
{
    // Arrange
    string deviceId = "testDeviceId";
    Device expectedDevice = new Device(deviceId);

    // Create a mock IotHubServiceClient
    Mock<IotHubServiceClient> mockIotHubServiceClient = new Mock<IotHubServiceClient>();
    mockIotHubServiceClient
            .Setup(c => c.Devices.GetAsync(It.IsAny<string>(), It.IsAny<CancellationToken>()))
            .ReturnsAsync(expectedDevice);

    // Create an instance of IoTHubService using the mock client
    IotHubService ioTHubService = new IotHubService(mockIotHubServiceClient.Object);

    // Act
    Device result = await ioTHubService.GetDeviceByIdAsync(deviceId);

    // Assert
    Assert.Equal(expectedDevice, result);
    mockIotHubServiceClient.Verify(c => c.Devices.GetAsync(deviceId, default(CancellationToken)), Times.Once);
}

但是,我没有成功模拟 IotHubServiceClient 并在运行测试时收到以下错误:

System.NotSupportedException:非虚拟(可在 VB 中重写)成员上的设置无效:mock => mock.Devices`

我知道底层

DevicesClient
是密封的,但我想知道是否有办法解决这个问题?

编辑:我的

IotHubService
课程是什么样的:

public class IotHubService : IIotHubService
    {
        protected readonly IotHubServiceClient _iotHubServiceClient;

        public IotHubService(string connectionString)
        {
            _iotHubServiceClient = new IotHubServiceClient(connectionString);
        }

        public IotHubService(IotHubServiceClient iotHubServiceClient)
        {
            _iotHubServiceClient = iotHubServiceClient;
        }

        public async Task<Device> GetDeviceByIdAsync(string deviceId)
        {
            if (string.IsNullOrEmpty(deviceId))
            {
                throw new ArgumentNullException(nameof(deviceId));
            }

            try
            {
                return await _iotHubServiceClient.Devices.GetAsync(deviceId);
            }
            catch (Exception)
            {
                throw;
            }
        }
    }
c# moq xunit azure-iot-sdk
1个回答
0
投票

IotHubService
与 Azure IoT 结合使用,我能够进行模拟和测试。

  • 带有模拟测试和单元测试的示例。
public class IotHubServiceTests
{
    
    private const string ConnectionString = "  ";

    [Fact]
    public async Task CheckDeviceConnection_DeviceExists_ReturnsTrue()
    {
        
        var iotHubService = new IotHubService(ConnectionString);
        var deviceId = " ";

       
        Device device = await iotHubService.GetDeviceByIdAsync(deviceId);

       
        Assert.NotNull(device);
        Assert.Equal(deviceId, device.Id);
        Assert.True(device.ConnectionState == DeviceConnectionState.Connected);

        
        if (device != null && device.ConnectionState == DeviceConnectionState.Connected)
        {
            Console.WriteLine("CheckDeviceConnection_DeviceExists_ReturnsTrue: Passed");
        }
        else
        {
            Console.WriteLine("CheckDeviceConnection_DeviceExists_ReturnsTrue: Failed");
        }
    }

    [Fact]
    public async Task CheckDeviceConnection_DeviceNotFound_ReturnsFalse()
    {
        
        var iotHubService = new IotHubService(ConnectionString);
        var deviceId = "nonexistent_device";

        
        Device device = await iotHubService.GetDeviceByIdAsync(deviceId);

        
        Assert.Null(device);

        
        if (device == null)
        {
            Console.WriteLine("CheckDeviceConnection_DeviceNotFound_ReturnsFalse: Passed");
        }
        else
        {
            Console.WriteLine("CheckDeviceConnection_DeviceNotFound_ReturnsFalse: Failed");
        }
    }

    [Fact]
    public async Task CheckDeviceConnection_NullDeviceId_ThrowsArgumentNullException()
    {
       
        var iotHubService = new IotHubService(ConnectionString);
        string deviceId = null;

        
        await Assert.ThrowsAsync<ArgumentNullException>(() => iotHubService.GetDeviceByIdAsync(deviceId));

        
        Console.WriteLine("CheckDeviceConnection_NullDeviceId_ThrowsArgumentNullException: Passed");
    }
}

public class IotHubService
{
    private readonly RegistryManager _registryManager;

    public IotHubService(string connectionString)
    {
        _registryManager = RegistryManager.CreateFromConnectionString(connectionString);
    }

    public async Task<Device> GetDeviceByIdAsync(string deviceId)
    {
        if (string.IsNullOrEmpty(deviceId))
        {
            throw new ArgumentNullException(nameof(deviceId));
        }

        try
        {
            return await _registryManager.GetDeviceAsync(deviceId);
        }
        catch (DeviceNotFoundException)
        {
            
            return null;
        }
        catch (Exception ex)
        {
            throw ex;
        }
    }
}
static void Main(string[] args)
{
    Console.WriteLine("Running Xunit tests...");

   
    var assembly = typeof(Program).Assembly;
    var assemblyLocation = System.Reflection.Assembly.GetExecutingAssembly().Location;
    var result = Xunit.ConsoleClient.Program.Main(new[] { assemblyLocation });

    if (result == 0)
    {
        Console.WriteLine("Xunit tests passed.");
    }
    else
    {
        Console.WriteLine("Xunit tests failed.");
    }

    Console.WriteLine("Press any key to exit...");
    Console.ReadKey();
}

输出: enter image description here

  • 有关更多详细信息,请参阅 this gitSO
© www.soinside.com 2019 - 2024. All rights reserved.