Pattern 11: Testing Without Hardware
Mock SDK
internal interface ISdkClient
{
Task<bool> OpenDoor(uint address, uint doorId, CancellationToken cancellationToken);
Task<DeviceInfo> GetDeviceInfo(uint address, CancellationToken cancellationToken);
}
internal sealed class RealSdkClient : ISdkClient
{
// actual SDK implementation
}
internal sealed class MockSdkClient : ISdkClient
{
public Task<bool> OpenDoor(uint address, uint doorId, CancellationToken cancellationToken)
{
Console.WriteLine($"Mock: Opening door {doorId} on device {address}");
return Task.FromResult(true);
}
public Task<DeviceInfo> GetDeviceInfo(uint address, CancellationToken cancellationToken)
{
return Task.FromResult(new DeviceInfo
{
Model = "MockDevice",
FirmwareVersion = "1.0.0"
});
}
}
DI Configuration
// In appsettings.Development.json
{
"Adapter": {
"UseMockSdk": true
}
}
// In DI registration
if (configuration.GetValue<bool>("Adapter:UseMockSdk"))
services.AddSingleton<ISdkClient, MockSdkClient>();
else
services.AddSingleton<ISdkClient, RealSdkClient>();
Simulating Events
internal sealed class MockSdkClient : ISdkClient
{
private readonly Timer _eventTimer;
public event EventHandler<DeviceEvent>? OnEvent;
public MockSdkClient()
{
// simulate events every 5 seconds
_eventTimer = new Timer(_ => SimulateEvent(), null,
TimeSpan.FromSeconds(5), TimeSpan.FromSeconds(5));
}
private void SimulateEvent()
{
var evt = new DeviceEvent(
Code: 0x1000, // Access Granted
Timestamp: DateTime.UtcNow,
DoorId: 1,
PersonId: 12345,
CredentialId: 67890,
RawData: Array.Empty<byte>()
);
OnEvent?.Invoke(this, evt);
}
}
Integration Tests
[Fact]
public async Task OpenDoor_SendsCorrectCommand()
{
// Arrange
var mockSdk = new MockSdkClient();
var protocol = new Protocol(mockSdk, ...);
// Act
var result = await protocol.OpenDoor(doorId: 1, CancellationToken.None);
// Assert
Assert.True(result);
Assert.Equal(1, mockSdk.CommandsSent.Count);
Assert.Equal("OpenDoor", mockSdk.CommandsSent[0].Type);
}
Benefits of Mocking
- Fast iteration - no hardware setup required
- CI/CD compatible - tests run in pipeline
- Edge case testing - simulate rare conditions
- Parallel development - work before hardware arrives
- Regression testing - automated test suite