2

RegistryManagerIoThub との通信に使用するクラスをテストしようとしています。

私が直面している問題は、から継承するモック クラスを作成するときに、 をRegistryManager除くすべてのメソッドをオーバーライドできることですExportRegistryAsync。オーバーライドの下に赤い線が表示され、オーバーライド ステートメントを削除すると、プロジェクトのビルド時に次のエラーが発生します。

エラー 4 'MockObjects.MockRegistryManager' は、継承された抽象メンバー 'Microsoft.Azure.Devices.RegistryManager.ExportRegistryAsync(string, string)' Tests\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か?

どんな助けでも大歓迎です。

4

1 に答える 1

2

テストするクラスの現在のバージョンが与えられた場合

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;
    }
}

これをテストしたい場合は、RegistryManager. 使用するサービスを抽象化して、本物を使用せずにテスト用にモック/偽造できるようにする必要があります。

何かのようなもの

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);
    }
}

このアプローチの良い点の 1 つは、依存クラスに本当に必要な機能のみを公開する必要があることです。

を使用Moqして、次のテストでクラスFluentAssertionsをモックアップしてテストすることができましたRegistry

[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);
}

お役に立てれば。

于 2016-04-15T16:22:47.557 に答える