在web api 2

时间:2018-02-12 09:43:30

标签: c# testing asp.net-web-api integration-testing autofac

我在集成测试中手动实例化了我的服务,但是当我接到一个具有 Lazy 依赖关系的服务时,我做了一些研究,发现you can actually use Autofac to resolve your services when doing your tests

所以,我写了这个课:

public class Container<TModule> where TModule: IModule, new()
{
    private readonly IContainer _container;

    protected Container()
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule(new TModule());
        _container = builder.Build();
    }

    protected TEntity Resolve<TEntity>() => _container.Resolve<TEntity>();
    protected void Dispose() => _container.Dispose();
}

然后在我的背景下,我改为:

public class ProductContext : Container<AutofacModule>
{
    public IProductProvider ProductProvider { get; }
    public static ProductContext GiventServices() => new ProductContext();

    protected ProductContext()
    {
        ProductProvider = Resolve<IProductProvider>();
    }

    public List<JObject> WhenListProducts(int categoryId) => ProductProvider.List(categoryId);
}

我有另一个似乎有用的上下文(测试通过),并使用 MatchProvider 。如果我在 Autofac 模块中进行比较,它们看起来像这样:

builder.RegisterType<ProductProvider>().As<IProductProvider>().InstancePerRequest();

builder.RegisterType<MatchProvider>().As<IMatchProvider>().SingleInstance();

因为 MatchProvider 是一个singelton,它似乎没有问题得到解决,但 ProductProvider 是每个请求的实例,这就是问题所在

运行任何需要该服务的测试时出现此错误:

  

没有标记匹配的范围&#39; AutofacWebRequest&#39;从请求实例的范围可见。

我认为这是因为我没有安装正确的nuget包。所以我安装了:

  • Autofac
  • Autofac.Integration.Owin
  • Autofac.Integration.WebApi
  • Autofac.Integration.WebApi.Owin

这些是我的模块定义时使用的相同参考,但这没有用。 有谁知道我需要做些什么才能让它发挥作用?

1 个答案:

答案 0 :(得分:2)

我无法找到合适的(简单)解决方案。我看到有些人自己创造了一生的范围,这对我来说似乎有点矫枉过正,而且它并不是很好的。#34;码。 因此,采用 Autofac 原则之一:任何多次注册的服务;最后一个实例是已解析的实例。

因此,在我的 $('#spinner').fadeOut(); 课程中,我只是将我的 InstancePerRequest 服务重新注册为 InstancePerDependency 。这解决了我的问题。 这是我的完整代码:

$(document).ready(function(){
    $("#spinner").fadeOut();
});

然后,我使用的任何上下文都继承了这个类:

Container

这意味着,在测试时,我可以这样做:

public class ContainerContext<TModule> where TModule: IModule, new()
{
    private IContainer _container;

    protected ContainerContext()
    {
        var builder = new ContainerBuilder();
        builder.RegisterModule(new TModule());

        // Because Autofac will resolve services using the last registration, we can change all our web api 
        // services to by InstancePerDependency instead of InstancePerRequest which is obviously better
        // when testing.
        builder.RegisterType<AnswerProvider>().As<IAnswerProvider>().InstancePerDependency();
        builder.RegisterType<AttributeProvider>().As<IAttributeProvider>().InstancePerDependency();
        builder.RegisterType<CategoryProvider>().As<ICategoryProvider>().InstancePerDependency();
        builder.RegisterType<ClaimProvider>().As<IClaimProvider>().InstancePerDependency();
        builder.RegisterType<ClientProvider>().As<IClientProvider>().InstancePerDependency();
        builder.RegisterType<CriteriaProvider>().As<ICriteriaProvider>().InstancePerDependency();
        builder.RegisterType<FeedProvider>().As<IFeedProvider>().InstancePerDependency();
        builder.RegisterType<FormulaProvider>().As<IFormulaProvider>().InstancePerDependency();
        builder.RegisterType<ImageProvider>().As<IImageProvider>().InstancePerDependency();
        builder.RegisterType<GroupProvider>().As<IGroupProvider>().InstancePerDependency();
        builder.RegisterType<QuestionProvider>().As<IQuestionProvider>().InstancePerDependency();
        builder.RegisterType<StripeProvider>().As<IStripeProvider>().InstancePerDependency();

        builder.RegisterType<ApiAiProvider>().As<IApiAiProvider>().InstancePerDependency();
        builder.RegisterType<PiiikProvider>().As<IPiiikProvider>().InstancePerDependency();
        builder.RegisterType<ProductProvider>().As<IProductProvider>().InstancePerDependency();
        builder.RegisterType<SettingProvider>().As<ISettingProvider>().InstancePerDependency();
        builder.RegisterType<TrackingProvider>().As<ITrackingProvider>().InstancePerDependency();

        _container = builder.Build();
    }

    protected TEntity Resolve<TEntity>() => _container.Resolve<TEntity>();
    protected void Dispose() => _container.Dispose();
}

这可以帮助其他人遇到同样的问题。