container.RegisterWebApiControllers(GlobalConfiguration.Configuration)导致出现InvalidOperationException [英] container.RegisterWebApiControllers(GlobalConfiguration.Configuration) causes InvalidOperationException

查看:1409
本文介绍了container.RegisterWebApiControllers(GlobalConfiguration.Configuration)导致出现InvalidOperationException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的集成测试我使用我在我测试Web API项目建设同样SimpleInjector.Container。

不过,这条线组成的根类:

  container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

导致异常:

  System.TypeInitializationException:为MyProject.Api.Test.Integration.HttpClientFactory'的类型初始值引发了异常。
---- System.InvalidOperationException:此方法不能在应用程序的pre-启动初始化阶段被调用。
结果堆栈跟踪:
在MyProject.Api.Test.Integration.HttpClientFactory.Create()
   在MyProject.Api.Test.Integration.Controllers.ProductControllerIntegrationTest.<GetProductBar$c$c_Should_Return_Status_BadRequest_When_Bar$c$c_Is_Empty>d__0.MoveNext()在d:\\项目\\我\\ MyProject.Api.Test.Integration \\ \\控制器ProductControllerIntegrationTest.cs:第26行
-----内堆栈跟踪-----
   在System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled()
   在System.Web.Compilation.BuildManager.GetReferencedAssemblies()
   在System.Web.Http.WebHost.WebHostAssembliesResolver.System.Web.Http.Dispatcher.IAssembliesResolver.GetAssemblies()
   在System.Web.Http.Dispatcher.DefaultHttpControllerTypeResolver.GetControllerTypes(IAssembliesResolver assembliesResolver)
   在System.Web.Http.WebHost.WebHostHttpControllerTypeResolver.GetControllerTypes(IAssembliesResolver assembliesResolver)
   在SimpleInjector.SimpleInjectorWebApiExtensions.GetControllerTypesFromConfiguration(HttpConfiguration配置)
   在SimpleInjector.SimpleInjectorWebApiExtensions.RegisterWebApiControllers(集装箱货柜,HttpConfiguration配置)
   在MyProject.Api.ContainerConfig.RegisterTypes(集装箱货柜)在d:\\项目\\我\\ MyProject.Api \\ App_Start \\ ContainerConfig.cs:128线
   在MyProject.Api.ContainerConfig.CreateWebApiContainer()在d:\\项目\\我\\ MyProject.Api \\ App_Start \\ ContainerConfig.cs:行63
   在MyProject.Api.Test.Integration.HttpClientFactory..cctor()在d:\\项目\\我\\ MyProject.Api.Test.Integration \\ HttpClientFactory.cs:17行

评论它后一切工作正常,无论是Web应用程序本身和测试。

所以,问题是:


  • 什么是异常的原因是什么?

  • (而且这种方法真正需要的?)

这里的code为HttpClientFactory(一个辅助类来创建HttpClient的适当标题,如API密钥或授权):

 内部静态类HttpClientFactory
{
    私人静态只读集装箱_container = ContainerConfig.CreateWebApiContainer();    公共静态的HttpClient的Create()
    {
        VAR的客户=新的HttpClient {BaseAddress =的getURL()};
        // ...
        返回客户端;
    }
}


解决方案

如果我们在堆栈跟踪仔细观察,我们可以确切地看到是怎么回事。在 RegisterWebApiControllers 扩展方法调用上的 GetControllerTypes 方法 IHttpControllerTypeResolver 比如,它从 HttpConfiguration 抓住并传递 IAssembliesResolver ,它也从配置检索。在名为 GetControllerTypes 法(的 WebHostHttpControllerTypeResolver )调用到 GetControllerTypes DefaultHttpControllerTypeResolver 这将最终导致 GetReferencedAssemblies 一通话的System.Web .Compilation.BuildManager 类。

System.Web.Compilation.BuildManager 但是,不能在ASP.NET管道叫早,或ASP.NET在所有的环境之外。既然你是在一个测试中, BuildManage 将抛出您所遇到的除外。

因此​​溶液(或'绝招',所以你会)这里是替换默认 IAssembliesResolver 时,单元测试。我想,解析看起来是这样的:

 公共类TestAssembliesResolver:IAssembliesResolver
{
    公众的ICollection&LT;大会&GT; GetAssemblies()
    {
        返回AppDomain.CurrentDomain.GetAssemblies();
    }
}[测试方法]
公共无效TestMethod1()
{
    //替换原有IAssembliesResolver。
    GlobalConfiguration.Configuration.Services.Replace(typeof运算(IAssembliesResolver)
        新TestAssembliesResolver());    变种容器= SimpleInjectorWebApiInitializer.BuildContainer();    container.Verify();
}

这是有点遗憾的是,你必须处理这一点,特别是因为简单的注射器被设计为可测试。看来,我们用的Web API这么深整合 RegisterWebApiControllers 扩展方法忽略这一点。我们必须退一步想想如何更容易地确认一个单元测试内部的Web API配置。

In my integration tests I'm using the same SimpleInjector.Container which I construct in the Web API project I'm testing.

But this line in composition root class:

container.RegisterWebApiControllers(GlobalConfiguration.Configuration);

causes an exception:

System.TypeInitializationException : The type initializer for 'MyProject.Api.Test.Integration.HttpClientFactory' threw an exception.
---- System.InvalidOperationException : This method cannot be called during the application's pre-start initialization phase.
Result StackTrace:  
at MyProject.Api.Test.Integration.HttpClientFactory.Create()
   at MyProject.Api.Test.Integration.Controllers.ProductControllerIntegrationTest.<GetProductBarcode_Should_Return_Status_BadRequest_When_Barcode_Is_Empty>d__0.MoveNext() in d:\Projects\My\MyProject.Api.Test.Integration\Controllers\ProductControllerIntegrationTest.cs:line 26
----- Inner Stack Trace -----
   at System.Web.Compilation.BuildManager.EnsureTopLevelFilesCompiled()
   at System.Web.Compilation.BuildManager.GetReferencedAssemblies()
   at System.Web.Http.WebHost.WebHostAssembliesResolver.System.Web.Http.Dispatcher.IAssembliesResolver.GetAssemblies()
   at System.Web.Http.Dispatcher.DefaultHttpControllerTypeResolver.GetControllerTypes(IAssembliesResolver assembliesResolver)
   at System.Web.Http.WebHost.WebHostHttpControllerTypeResolver.GetControllerTypes(IAssembliesResolver assembliesResolver)
   at SimpleInjector.SimpleInjectorWebApiExtensions.GetControllerTypesFromConfiguration(HttpConfiguration configuration)
   at SimpleInjector.SimpleInjectorWebApiExtensions.RegisterWebApiControllers(Container container, HttpConfiguration configuration)
   at MyProject.Api.ContainerConfig.RegisterTypes(Container container) in d:\Projects\My\MyProject.Api\App_Start\ContainerConfig.cs:line 128
   at MyProject.Api.ContainerConfig.CreateWebApiContainer() in d:\Projects\My\MyProject.Api\App_Start\ContainerConfig.cs:line 63
   at MyProject.Api.Test.Integration.HttpClientFactory..cctor() in d:\Projects\My\MyProject.Api.Test.Integration\HttpClientFactory.cs:line 17

After commenting it everything works fine, both the web app itself and the tests.

So the question is:

  • What is the reason for the exception?
  • (And is this method really required?)

Here's the code for HttpClientFactory (a helper class to create HttpClient with proper headers, such as api key or authorization):

internal static class HttpClientFactory
{
    private static readonly Container _container = ContainerConfig.CreateWebApiContainer();

    public static HttpClient Create()
    {
        var client = new HttpClient { BaseAddress = GetUrl() };
        //...
        return client;
    }
}

解决方案

If we look closely at the stack trace we can exactly see what is going on here. The RegisterWebApiControllers extension method calls the GetControllerTypes method on the IHttpControllerTypeResolver instance it grabs from the HttpConfiguration and it passes the IAssembliesResolver that is also retrieved from the configuration. The called GetControllerTypes method (of the WebHostHttpControllerTypeResolver) calls into the GetControllerTypes of the DefaultHttpControllerTypeResolver which will eventually cause a call to GetReferencedAssemblies of the System.Web.Compilation.BuildManager class.

The System.Web.Compilation.BuildManager however, can not be called early in the ASP.NET pipeline, or outside the context of ASP.NET at all. Since you're in a test, the BuildManage will throw the exception you are experiencing.

So the solution (or 'trick' so you will) here is to replace the default IAssembliesResolver when unit testing. I imagine that resolver to look like this:

public class TestAssembliesResolver : IAssembliesResolver
{
    public ICollection<Assembly> GetAssemblies()
    {
        return AppDomain.CurrentDomain.GetAssemblies();
    }
}

[TestMethod]
public void TestMethod1()
{
    // Replace the original IAssembliesResolver.
    GlobalConfiguration.Configuration.Services.Replace(typeof(IAssembliesResolver),
        new TestAssembliesResolver());

    var container = SimpleInjectorWebApiInitializer.BuildContainer();

    container.Verify();
}

It's a bit unfortunate that you have to deal this, especially since Simple Injector was designed to be testable. It seems that we overlooked this by integrating the RegisterWebApiControllers extension method so deeply with Web API. We have to take a step back and think about how to make it easier to verify the Web API configuration inside a unit test.

这篇关于container.RegisterWebApiControllers(GlobalConfiguration.Configuration)导致出现InvalidOperationException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆