我有一个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.UseContentRoot
和builder.UseSolutionRelativeContentRoot
配置自定义WebApplicationFactory,但是无论我为ContentRoot
方法使用什么值,它都会抛出相同的错误。
我不知道为什么当Clean Architecture示例中的测试正在运行时,我的测试为什么失败。我也不知道该如何解决。
任何指针都将受到高度赞赏!
答案 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)
答案 5 :(得分:0)
似乎WebApplicationFactory应该使用实际的Startup类作为参数类型:
class TestWebApplicationFactory : WebApplicationFactory<Startup>
{
protected override IWebHostBuilder CreateWebHostBuilder()
{
return WebHost.CreateDefaultBuilder<TestableStartup>();
}
}
请注意,“启动”是真实SUT代码上的类型,而“ TestableStartup”是TestingStartup配置。