你的位置:首页 > ASP.net教程

[ASP.net教程]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; } }}

运行结果: