Container.RegisterWebApiControllers (GlobalConfiguration.Configuration) throws an InvalidOperationException

In my integration tests, I use the same SimpleInjector.Container that I create in the web API project that I am testing.

But this line in the root composition class:

container.RegisterWebApiControllers(GlobalConfiguration.Configuration); 

throws 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 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, everything works fine, both with the web application itself and with the tests.

So the question is:

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

Here is the code for the HttpClientFactory (helper class for creating the HttpClient with the appropriate headers, for example, 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; } } 
+5
source share
2 answers

If we carefully consider the stack trace, we can see exactly what is happening here. The RegisterWebApiControllers extension method calls the GetControllerTypes method on the GetControllerTypes instance, which it grabs from HttpConfiguration , and it passes the IAssembliesResolver , which is also retrieved from the configuration. The GetControllerTypes method called ( WebHostHttpControllerTypeResolver ) calls GetControllerTypes DefaultHttpControllerTypeResolver , which ultimately calls the GetReferencedAssemblies call of the GetReferencedAssemblies class.

However, System.Web.Compilation.BuildManager cannot be called at the beginning of the ASP.NET pipeline or outside the ASP.NET context. Since you are in a test, BuildManage will throw an exception that you are experiencing.

So the solution (or the โ€œtrickโ€, so you will be here) should replace the standard IAssembliesResolver in unit testing. I assume the resolver is as follows:

 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 little annoying that you have to deal with this, especially since Simple Injector was designed for verification. It looks like we missed this by integrating the RegisterWebApiControllers extension method so deep into the Web API. We should take a step back and think about how to simplify the verification of the web API configuration inside the unit test.

+5
source

The solution for SI v3.x is fair ...

 container.RegisterWebApiControllers( GlobalConfiguration.Configuration, Assembly.GetExecutingAssembly() ); 

.. so now he knows the assembly for finding the controllers.

+3
source

Source: https://habr.com/ru/post/1206061/


All Articles