2

クラスでは、次のコードを使用しています。

    public User CurrentUser
    {
        get
        {
            var unityContainer = new UnityContainer();
            var httpContextHelper = unityContainer.Resolve<HttpContextHelper>();
            return httpContextHelper.GetUser();
        }
    }

これはBootstrapper.csファイルにあります:

public static class Bootstrapper
{
    public static void Initialise()
    {
        IUnityContainer unityContainer = new UnityContainer();
        unityContainer.RegisterType<IHttpContextHelper, HttpContextHelper>();
        DependencyResolver.SetResolver(new UnityDependencyResolver(unityContainer));
    }
}

コンストラクターインジェクションは基本クラスであり、リファクタリングにはかなりの作業が必要になるため、ここでは使用できません。

しかし、これをどのように単体テストしますか?モックするのに適した方法が見つかりませんunityContainer.Resolve

4

1 に答える 1

11

まず最初に、次のコードが間違っています。

get
{
    var unityContainer = new UnityContainer();
    var httpContextHelper = unityContainer.Resolve<HttpContextHelper>();
    return httpContextHelper.GetUser();
}

もちろん空の新しいUnityコンテナーを作成してから、このコンテナーからいくつかのインスタンスを解決しようとしています。これは、HttpContextHelperクラスのデフォルトコンストラクターを呼び出すだけです。コンテナに登録されたことがないもののインスタンスを解決しようとしたときに例外をスローしないことでUnityが嫌いです(これはここで行っていることです)。代わりに、最も既知の(登録された)依存関係を使用してコンストラクターをサイレントに呼び出しています。

したがって、インスタンスを登録したUnityContainerの別のインスタンスがあるため、Bootstrapperに登録したインスタンスは返されませんIHttpContextHelper

したがって、これをリファクタリングするための最初のステップは、DependencyResolverを使用することです。

public User CurrentUser
{
    get
    {
        var httpContextHelper = DependencyResolver
            .Current
            .GetService<IHttpContextHelper>();
        return httpContextHelper.GetUser();
    }
}

これで、単体テストでカスタム依存関係リゾルバーを作成できます。

public class DepepndecyResolverMock : IDependencyResolver
{
    private readonly IDictionary<Type, object> kernel;
    public DepepndecyResolverMock(IDictionary<Type, object> kernel)
    {
        this.kernel = kernel;
    }

    public object GetService(Type serviceType)
    {
        return this.kernel[serviceType];
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        throw new NotImplementedException();
    }
}

テスト用に構成できます。

var kernel = new Dictionary<Type, object>
{
    { typeof(IHttpContextHelper), new HttpContextHelperMock() }
};
DependencyResolver.SetResolver(new DepepndecyResolverMock(kernel));

そうは言っても、このコードはまだひどく間違っています。それはあなたがそれをユニットテストすることを可能にするかもしれません、しかし私が主張してください、これは間違ったデザインです。使用しないでください。これは、アンチパターンであるサービスロケーターパターンを使用します。

これを行う適切な方法は、このクラスの制御を反転して、依存関係をフェッチする必要がないようにすることですが、依存関係を注入する必要があります。したがって、無駄なパターンで時間を無駄にするのではなく、実際の依存性注入を使用するようにコードをリファクタリングします。

于 2012-12-23T16:47:19.993 に答える