2016-04-15 15 views
1

我想測試我的類,它使用RegistryManager與IoThub進行通信。單元測試使用RegistryManager C#Azure的類IoTHub

我面臨的問題是,當創建一個繼承自RegistryManager的模擬類時,我可以覆蓋除ExportRegistryAsync之外的所有方法。我得到一個紅色的線下覆蓋,如果我刪除替換語句時,我建這個項目我得到這個錯誤:

錯誤4「MockObjects.MockRegistryManager」不實現繼承的抽象成員「Microsoft.Azure.Devices。 RegistryManager.ExportRegistryAsync(字符串,字符串)」測試\ MockObjects \ MockRegistryManager.cs 9月18日

代碼:

public class MockRegistryManager : RegistryManager 
{ 
    private static List<Device> _devices; 

    public MockRegistryManager() 
    { 
     _devices = new List<Device>(); 
    } 

    public override Task OpenAsync() 
    { 
     throw new NotImplementedException(); 
    } 


    ... 


    internal override Task ExportRegistryAsync(string storageAccountConnectionString, string containerName) 
    { 
     throw new NotImplementedException(); 
    } 

    internal override Task ExportRegistryAsync(string storageAccountConnectionString, string containerName, CancellationToken cancellationToken) 
    { 
     throw new NotImplementedException(); 
    } 

} 

是否有更好的方法來測試使用RegistryManager類?

任何幫助將非常感激。

+0

你是什麼意思的紅線覆蓋下?如果你重寫,它是編譯還是不編譯? – Nitin

+0

你可以將你要使用的方法和屬性抽象到一個接口中,這樣你就可以將它與「RegistryManager」緊密耦合在一起。你不應該試圖嘲笑你不擁有的課程。 – Nkosi

+0

你能展示一個使用或依賴'RegistryManager'的類的片段嗎 – Nkosi

回答

2

給你之類的當前版本中如果你想測試這個,那麼你將與RegistryManager問題測試

public class Registry { 
    private readonly RegistryManager _registryManager; 

    public Registry(RegistryManager rm) { 
     _registryManager = rm; 
    } 

    public async Task<string> GetDeviceKey(string deviceId = null) { 
     if (deviceId == null) { 
      throw new Exception("Todo replace"); 
     } 
     var device = await _registryManager.GetDeviceAsync(deviceId); 
     if (device == null) { 
      throw new Exception("TODO replace"); 
     } 
     return device.Authentication.SymmetricKey.PrimaryKey; 
    } 
} 

。您需要抽象您想要使用的服務,以便您可以嘲笑/僞造它們進行測試,而無需使用真實的東西。

public interface IRegistryManager { 
    Task<Device> GetDeviceAsync(string deviceId); 
} 

這一操作將讓你重構你的類像這樣

public class Registry { 
    private readonly IRegistryManager _registryManager; 

    public Registry(IRegistryManager rm) { 
     _registryManager = rm; 
    } 

    public async Task<string> GetDeviceKey(string deviceId = null) { 
     if (deviceId == null) { 
      throw new Exception("Todo replace"); 
     } 
     var device = await _registryManager.GetDeviceAsync(deviceId); 
     if (device == null) { 
      throw new Exception("TODO replace"); 
     } 
     return device.Authentication.SymmetricKey.PrimaryKey; 
    } 
} 

現在允許你Registry類是完全測試。您會注意到,除了註冊表管理器字段的類型之外,沒有其他需要更改。不錯。

您現在可以根據需要使用測試框架製作假冒RegistryManager或模擬一個。

當你需要在你的產品代碼實際調用你只是包裝真實的東西在你的界面,並把它傳遞到您的Registry

public class ActualRegistryManager : IRegistryManager { 
    private readonly RegistryManager _registryManager 

    public ActualRegistryManager (RegistryManager manager) { 
     _registryManager = manager; 
    } 

    public Task<Device> GetDeviceAsync(string deviceId) { 
     return _registryManager.GetDeviceAsync(deviceId); 
    } 
} 

一個這種方法的好東西就是你現在只需要將你真正需要的功能暴露給依賴類。

使用MoqFluentAssertions我能夠小樣,並與下面的測試

[TestMethod] 
public async Task Registry_Should_Return_DeviceKey() { 
    //Arrange 
    var expectedPrimaryKey = Guid.NewGuid().ToString(); 
    var deviceId = Guid.NewGuid().ToString(); 
    var fakeDevice = new Device(deviceId) { 
     Authentication = new AuthenticationMechanism { 
      SymmetricKey = new SymmetricKey { 
       PrimaryKey = expectedPrimaryKey 
      } 
     } 
    }; 
    var registryManagerMock = new Mock<IRegistryManager>(); 
    registryManagerMock.Setup(m => m.GetDeviceAsync(deviceId)) 
     .ReturnsAsync(fakeDevice); 
    var registry = new Registry(registryManagerMock.Object); 

    //Act     
    var deviceKey = await registry.GetDeviceKey(deviceId); 

    //Assert 
    deviceKey.Should().BeEquivalentTo(expectedPrimaryKey); 
} 

希望這有助於測試Registry類。

+1

@Nikosi謝謝! – Reginbald

+0

沒問題。樂意效勞。 – Nkosi