I have a class IotHubService that depends on the C# IoTHub SDK's IotHubServiceClient (v2 version of the SDK, currently in preview) to perform various queries on an IoTHub. I'm trying to improve the reliability of my class by writing some tests and mocking dependencies:
[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);
}
However, I'm unsuccesful in mocking the IotHubServiceClient and receive the following error when running my test:
System.NotSupportedException : Invalid setup on a non-virtual (overridable in VB) member: mock => mock.Devices`
I understand that the underlying DevicesClient is sealed, but I was wondering if there is any way solve this problem?
Edit: What my IotHubService class looks like:
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;
}
}
}
Using
IotHubServicewith Azure IoT, I am able to mock and test.Output:
With Mocking and Testing: