5

In meinen Integrationstests verwende ich denselben SimpleInjector.Container, den ich in dem Web-API-Projekt erstelle, das ich gerade teste.container.RegisterWebApiControllers (GlobalConfiguration.Configuration) verursacht InvalidOperationException

Aber diese Linie in der Zusammensetzung Wurzelklasse:

container.RegisterWebApiControllers(GlobalConfiguration.Configuration); 

verursacht eine Ausnahme:

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 

Nachdem es zu kommentieren alles funktioniert gut, sowohl den Web-App selbst und die Tests.

Die Frage ist also:

  • Was ist der Grund für die Ausnahme ist?
  • (Und ist diese Methode wirklich erforderlich?)

für HttpClientFactory der Code Hier ist (eine Hilfsklasse Httpclient mit der richtigen Header, wie api Schlüssel oder Berechtigung zum Anlegen):

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

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

Können Sie die InnerException- und StackTrace-Details posten? Haben Sie verbindliche Redirects in Ihrer Konfigurationsdatei? –

+1

Ich stimme @DarinDimitrov zu, bitte geben Sie uns die volle Stack-Trace. Ohne diese Details ist es schwierig, darüber nachzudenken. – Steven

+0

@Darin: Aktualisiert, danke! Bindungsumleitungen sind denen in Web.config sehr ähnlich. – abatishchev

Antwort

5

Wenn Wir schauen uns die Stack-Spur genauer an und können genau sehen, was hier vor sich geht. Die Erweiterungsmethode RegisterWebApiControllers ruft die GetControllerTypes-Methode auf der IHttpControllerTypeResolver-Instanz auf, die sie von der HttpConfiguration erhält, und sie übergibt die IAssembliesResolver, die ebenfalls aus der Konfiguration abgerufen wird. Das aufgerufene GetControllerTypes-Verfahren (von WebHostHttpControllerTypeResolver) ruft die GetControllerTypes der DefaultHttpControllerTypeResolver an, die schließlich einen Anruf an GetReferencedAssemblies der System.Web.Compilation.BuildManager-Klasse verursachen wird.

Die System.Web.Compilation.BuildManager kann jedoch nicht früh in der ASP.NET-Pipeline oder außerhalb des Kontexts von ASP.NET überhaupt aufgerufen werden. Da Sie sich in einem Test befinden, löst die BuildManage die Ausnahme aus, die Sie gerade erleben.

Also die Lösung (oder 'Trick' so werden Sie) hier ist, die Standard IAssembliesResolver beim Komponententest zu ersetzen. Ich stelle mir vor, dass Resolver wie folgt aussehen:

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(); 
} 

Es ist ein bisschen schade, dass Sie dies zu tun haben, zumal einfache Injector entworfen wurde prüfbar zu sein. Es scheint, dass wir dies übersehen haben, indem wir die Erweiterungsmethode RegisterWebApiControllers so tief mit der Web API integriert haben. Wir müssen einen Schritt zurück gehen und darüber nachdenken, wie es einfacher wird, die Web-API-Konfiguration in einem Komponententest zu überprüfen.

+0

Hallo Steven, ich sah, dass Sie vor kurzem die neue Version des Web Api-Integrationspakets veröffentlicht haben, aber dieses Problem wurde noch nicht behoben. – abatishchev

+0

@abatishchev: das ist richtig. v2.6.2 des Web-API-Integrationspakets behebt ausschließlich die Problemzustände [hier] (https://simpleinjector.codeplex.com/workitem/20987). Für den Moment müssen Sie mit der in meiner Antwort beschriebenen Problemumgehung arbeiten, oder schreiben Sie Ihre eigene benutzerdefinierte Controller-Registrierung, anstatt "RegisterWebApiControllers" aufzurufen. – Steven

+0

Hallo Steven, hast du irgendwelche Neuigkeiten/Pläne zur Behebung dieses Problems, bitte? – abatishchev

3

Eine Lösung für SI v3.x ist nur ...

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

.. so jetzt ist es um die Anordnung zu suchen Controllern kennt.

Verwandte Themen