ASP.NET 系列:单元测试之StructureMap

ASP.NET使用StructureMap等依赖注入组件时最重要就是EntityFramework的DbContext对象要保证在每次HttpRequest只有一个DbContext实例,这里将使用第三方提供的HttpSimulator进行测试。

1.定义IDependency接口

创建屏蔽不同依赖注入组件使用差别的接口。

public interface IDependency
{
    void Build();

    void EndRequest();

    void AddTransient(Type from, Type to, object instance = null);

    void AddScoped(Type from, Type to, object instance = null);

    void AddSingleton(Type from, Type to, object instance = null);

    object GetInstance(Type type);

    IEnumerable GetAllInstances(Type type);
}

2.提供StructureMap的适配类StructureMapAdapter

public class StructureMapAdapter : IDependency, IDisposable
{
    private bool _disposed = false;
    private Container _container;
    private Registry _registry;

    public StructureMapAdapter()
    {
        this._registry = new Registry();
    }

    public void Build()
    {
        _container = new Container(_registry);
    }

    public void EndRequest()
    {
        HttpContextLifecycle.DisposeAndClearAll();
    }

    public void AddTransient(Type from, Type to, object instance = null)
    {
        if (instance == null)
        {
            _registry.For(from).Use(to).LifecycleIs<TransientLifecycle>();
        }
        else
        {
            _registry.For(from).Use(instance).LifecycleIs<TransientLifecycle>();
        }
    }

    public void AddScoped(Type from, Type to, object instance = null)
    {
        if (instance == null)
        {
            _registry.For(from).Use(to).LifecycleIs<HttpContextLifecycle>();
        }
        else
        {
            _registry.For(from).Use(instance).LifecycleIs<HttpContextLifecycle>();
        }
    }

    public void AddSingleton(Type from, Type to, object instance = null)
    {
        if (instance == null)
        {
            _registry.For(from).Use(to).LifecycleIs<SingletonLifecycle>();
        }
        else
        {
            _registry.For(from).Use(instance).LifecycleIs<SingletonLifecycle>();
        }
    }

    public object GetInstance(Type type)
    {
        return _container.GetInstance(type);
    }

    public IEnumerable GetAllInstances(Type type)
    {
        return _container.GetAllInstances(type);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                this._container.Dispose();
            }

            _disposed = true;
        }
    }
}

3.使用HttpSimulator进行单元测试

public class StructureMapAdapterTest
{
    [Fact]
    public void TransientTest()
    {
        IDependency dependency = new StructureMapAdapter();
        dependency.AddTransient(typeof(ITest), typeof(Test));
        dependency.Build();
        var version1 = ((ITest)dependency.GetInstance(typeof(ITest))).Version;
        var version2 = ((ITest)dependency.GetInstance(typeof(ITest))).Version;
        Assert.NotEqual(version1, version2);
    }

    [Fact]
    public void SingletonTest()
    {
        IDependency dependency = new StructureMapAdapter();
        dependency.AddSingleton(typeof(ITest), typeof(Test));
        dependency.Build();
        var version1 = ((ITest)dependency.GetInstance(typeof(ITest))).Version;
        var version2 = ((ITest)dependency.GetInstance(typeof(ITest))).Version;
        Assert.Equal(version1, version2);
    }

    [Fact]
    public void ScopedTest()
    {
        var version1 = "";
        var version2 = "";
        using (HttpSimulator simulator = new HttpSimulator())
        {
            IDependency dependency = new StructureMapAdapter();
            dependency.AddScoped(typeof(ITest), typeof(Test));
            dependency.Build();
            simulator.SimulateRequest(new Uri("http://localhost/"));
            version1 = ((ITest)dependency.GetInstance(typeof(ITest))).Version;
            version2 = ((ITest)dependency.GetInstance(typeof(ITest))).Version;
            Assert.Equal(version1, version2);
        }

        using (HttpSimulator simulator = new HttpSimulator())
        {
            IDependency dependency = new StructureMapAdapter();
            dependency.AddScoped(typeof(ITest), typeof(Test));
            dependency.Build();
            simulator.SimulateRequest(new Uri("http://localhost/"));
            version1 = ((ITest)dependency.GetInstance(typeof(ITest))).Version;
        }
        using (HttpSimulator simulator = new HttpSimulator())
        {
            IDependency dependency = new StructureMapAdapter();
            dependency.AddScoped(typeof(ITest), typeof(Test));
            dependency.Build();
            simulator.SimulateRequest(new Uri("http://localhost/"));
            version2 = ((ITest)dependency.GetInstance(typeof(ITest))).Version;
        }
        Assert.NotEqual(version1, version2);
    }
}

public interface ITest
{
    String Version { get; }
}

public class Test : ITest
{
    private string _version = Guid.NewGuid().ToString();

    public string Version { get { return this._version; } }
}

运行结果:

posted @ 2016-02-05 11:22  秋天不会来  阅读(1502)  评论(0编辑  收藏  举报