在我的Web API中,我将Autofac链接为IoC容器,我这样做:
域级别
public class Autofac
{
protected ContainerBuilder Builder { get; set; }
public Autofac()
{
this.Builder = new ContainerBuilder();
}
public virtual IContainer Register()
{
// Register dependencies
SetUpRegistration(this.Builder);
// Build registration.
var container = this.Builder.Build();
// End
return container;
}
private static void SetUpRegistration(ContainerBuilder builder)
{
// === DATALAYER === //
// MyRepository
builder.RegisterType<MyRepository>()
.As<IMyRepository>()
.InstancePerLifetimeScope();
// === DOMAIN === //
// MyManager
builder.RegisterType<MyManager>()
.As<IMyManager>()
.InstancePerLifetimeScope();
}
}
Web API
public class Autofac : Domain.IoC.Autofac
{
public IContainer Register(HttpConfiguration config)
{
// Register your Web API controllers.
base.Builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// OPTIONAL: Register the Autofac filter provider.
base.Builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
// Complete registration and get container instance.
var container = base.Register();
// Set the dependency resolver to be Autofac.
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// Done.
return container;
}
}
如您所见,它继承自Domain的基类并设置特定于Web API的配置.
用法
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
new IoC.Autofac().Register(GlobalConfiguration.Configuration);
}
如你所知,这是在global.asax.
这个问题
这适用于Web API,但我不知道我需要做什么来在UnitTest项目上下文中注册所有这些.
我的想法是,我将在Web API级别为Autofac类创建一个类似的实现,但是与mocks(完全忽略Domain的基类)相比.
有什么指针吗?
解决方法:
就个人而言,我从来没有看到在单元测试中直接设置IoC容器的需要(我很难理解它的可行性或有用性).
由于单元测试用于测试一段逻辑代码,可以快速构建,轻松运行并且不需要太多(我主张不)拆卸.它不应要求为您的测试运行设置所有应用程序.
请记住,您的单元测试只是通过系统测试数据流,即您的DomainManager实际上会在您预期应该调用IRepository时调用它.然后,您将拥有所有存储库的单独测试类,以确定它们是否可以正确添加到数据库等.
我不确定你如何使用DBContext类,但作为一个包装器的例子,这就是它的样子.
interface IDBSetWrapper
{
object Add(object entity);
}
interface IDBContextWrapper
{
...
IDBSet Set(Type entityType);
...
}
class DBContextWrapper : IDBContextWrapper
{
private readonly DBContext context;
public DBContextWrapper()
{
context = new DBContext();
}
...
public IDBSet Set(Type entityType)
{
var dbSet = context.Set(entityType);
return new DBSetWrapper(dbSet);
}
...
}
它并不多,但我希望它能说明我对薄包装的意思.基本上包装器是DBContext并且将在类中包含它的实例,当您请求包装器执行任何操作时,将调用实际的DBContext.
我已经展示了当返回另一个对象(在这种情况下是一个DBSet)时会发生什么,这也将被包装在一个带有接口的单独对象中.这样您就可以轻松地模拟此类的返回值.
您现在可以将这个新的包装器添加到您的IoC中,因为它提供了一个接口.
有一点需要注意的是,你将无法并且可能不希望测试包装类,因为我看到它的意义非常小.但是之前我见过同事们对这类课程进行了集成测试.