WebApplicationFactory引发错误,表明ASP.NET Core集成测试中不存在contentRootPath

时间:2018-11-12 20:44:32

标签: c# asp.net-core integration-testing

我有一个ASP.NET Core项目,其中包含一些简单的Razor页面和一个Web API控制器。

我以Clean Architecture为起点。我已经重命名了项目名称,删除了MVC内容,并添加了一些自己的代码。一切运行正常。

但是,集成测试在调用factory.CreateClient()时会引发以下错误:

Test Name:  ToDo.Tests.Integration.Web.HomeControllerIndexShould.ReturnViewWithCorrectMessage
Test FullName:  ToDo.Tests.Integration.Web.HomeControllerIndexShould.ReturnViewWithCorrectMessage
Test Source:    C:\Source\Utopia\tests\ToDo.Tests\Integration\Web\HomeControllerIndexShould.cs : line 18
Test Outcome:   Failed
Test Duration:  0:00:00,001

Result StackTrace:  
at Microsoft.AspNetCore.Hosting.Internal.HostingEnvironmentExtensions.Initialize(IHostingEnvironment hostingEnvironment, String contentRootPath, WebHostOptions options)
   at Microsoft.AspNetCore.Hosting.WebHostBuilder.BuildCommonServices(AggregateException& hostingStartupErrors)
   at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build()
   at Microsoft.AspNetCore.TestHost.TestServer..ctor(IWebHostBuilder builder, IFeatureCollection featureCollection)
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateServer(IWebHostBuilder builder)
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.EnsureServer()
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateDefaultClient(DelegatingHandler[] handlers)
   at Microsoft.AspNetCore.Mvc.Testing.WebApplicationFactory`1.CreateClient(WebApplicationFactoryClientOptions options)
   at ToDo.Tests.Integration.Web.HomeControllerIndexShould..ctor(CustomWebApplicationFactory`1 factory) in C:\Source\Utopia\tests\ToDo.Tests\Integration\Web\HomeControllerIndexShould.cs:line 14
Result Message: 
System.ArgumentException : The content root 'C:\Source\Utopia\ToDo.Web' does not exist.
Parameter name: contentRootPath

我尝试使用builder.UseContentRootbuilder.UseSolutionRelativeContentRoot配置自定义WebApplicationFactory,但是无论我为ContentRoot方法使用什么值,它都会抛出相同的错误。

我不知道为什么当Clean Architecture示例中的测试正在运行时,我的测试为什么失败。我也不知道该如何解决。

任何指针都将受到高度赞赏!

6 个答案:

答案 0 :(得分:3)

我针对此问题的解决方案是使用应用程序启动定义<template> <v-layout justify-space-around row> <v-tabs v-model="selectedTab"> <v-tab v-for="tab in navbarTabs" :key="tab.id" :to=`/tabs/${tab.id}` >{{ tab.name }}</v-tab> </v-layout> </template> <script> export default { props: ['selectedTab'], } </script> ,而使用TestStartup设置WebApplicationFactory

示例:

WebHostBuilder

答案 1 :(得分:1)

我不完全确定您在说什么,但是首先您不应该在测试项目中配置类似的内容。相反,您应该创建一个类似TestStartup的类,并从SUT的Startup类继承。在SUT的Startup类中,应该将诸如数据库设置之类的事情分解为虚拟私有方法,然后可以在TestStartup上重写它们。例如,您可以创建如下方法:

private virtual void ConfigureDatabase(IServiceCollection services)
{
    services.AddDbContext<MyContext>(o =>
        o.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
}

然后在您的TestStartup中添加以下内容:

private override void ConfigureDatabase(IServiceCollection services)
{
    var databaseName = Guid.NewGuid().ToString();
    services.AddDbContext<MyContext>(o =>
        o.UseInMemoryDatabase(databaseName));
}

然后,在设置工厂进行测试时,您告诉工厂使用您的TestStartup

var client = factory.WithWebHostBuilder(b => b.UseStartup<TestStartup>()).CreateClient();

或者,您可以创建自己的自定义WebApplicationFactory并将其设置在此处:

public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<RazorPagesProject.Startup>
{
    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
        builder.UseStartup<TestStartup>();
    }
}

请记住,TStartup泛型类型参数是用于获取入口点程序集的,因此您仍然要将Startup放在此处。

主要要点是,您无需重复所有启动配置,然后记住保持同步。测试客户端将使用与实际应用程序完全相同的启动配置,除了一些保持替换(例如使用内存数据库)之外。

答案 2 :(得分:1)

如果您使用的是ReSharper,则可能与版本有关。我们发现版本2018.3。的问题添加UseSolutionRelativeContentRoot可以解决该问题。

    protected override void ConfigureWebHost(IWebHostBuilder builder)
    {
            builder.UseKestrel()
            .UseSolutionRelativeContentRoot("")
            .ConfigureAppConfiguration((context, configBuilder) =>
            {
              // Config code
            })
            .UseStartup<Startup>();
    }

答案 3 :(得分:1)

我的项目结构非常简单,遇到了同样的问题。项目结构:

-repo_root
 - myProject
   - myProject.csproj
   - src
 - myProjectTest
   - myProjectTest.csproj
   - tests

以上所有答案均不适用于我。我遍历了docs和其他与WebApplicationFactoryContentRootAttribute相关的资源,但无济于事。我还查看了WebApplicationFactory implementation,并尝试在设置中使用TEST_CONTENTROOT_APPNAME无效。

最终的帮助是在repo_root中创建了一个空的myProject.sln文件。

答案 4 :(得分:0)

这种方法对我有用

Buffer

有关更多信息,请参见How the test infrastructure infers the app content root path

答案 5 :(得分:0)

似乎WebApplicationFactory应该使用实际的Startup类作为参数类型:

class TestWebApplicationFactory : WebApplicationFactory<Startup>
{
     protected override IWebHostBuilder CreateWebHostBuilder()
     {
         return WebHost.CreateDefaultBuilder<TestableStartup>();
     }
}
  

请注意,“启动”是真实SUT代码上的类型,而“ TestableStartup”是TestingStartup配置。