我正在尝试使用 NUnit 为我的 Blazor WebAssembly Asp.Net-core 托管应用程序编写一个端端测试。
基于模板 3.1.7 创建了一个项目。然后我在解决方案中添加了一个 NUnit 项目并编写了一个简单的测试。
private const string serviceUrl = "https://localhost:50200";
private HttpClient _httpClient;
[OneTimeSetUp]
public void Init()
{
var arguments = new string[0];
var builder = Program.CreateHostBuilder(arguments);
_httpClient = new HttpClient();
builder
.ConfigureWebHostDefaults(w => w.UseUrls(serviceUrl))
.Build()
.Start();
}
[Test]
public async Task HomePageResponcesOk()
{
var requestUrl = serviceUrl;
var response = await _httpClient.GetAsync(requestUrl);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
[Test]
public async Task ApiResponcesOk()
{
var requestUrl = $"{serviceUrl}/WeatherForecast";
var response = await _httpClient.GetAsync(requestUrl);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
没有改变其他任何东西。
得到以下结果。
Test Duration Error Message
HomePageResponcesOk Failed 45 ms Expected: OK But was: NotFound
ApiResponcesOk Passed 364 ms
难道我做错了什么?
我还可以注意到,所有这些都适用于早期版本的 Blazor WebAssembly。
添加了更多测试
[Test]
public async Task AppCssResponcesOk()
{
var requestUrl = $"{serviceUrl}/css/app.css";
var response = await _httpClient.GetAsync(requestUrl);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
[Test]
public async Task WebAssemblyResponcesOk()
{
var requestUrl = $"{serviceUrl}/_framework/blazor.webassembly.js";
var response = await _httpClient.GetAsync(requestUrl);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
同样的事情Failed 45 ms Expected: OK But was: NotFound
。也许它app.UseStaticFiles();
不像我期望的那样工作?
我尝试
WebApplicationFactory<Startup>().CreateClient()
改用重做测试Program.CreateHostBuilder(arguments);
private const string serviceUrl = "";
private WebApplicationFactory<Startup> _factory;
private HttpClient _httpClient;
[OneTimeSetUp]
public void Init()
{
_factory = new WebApplicationFactory<Startup>();
_httpClient = _factory.CreateClient();
}
所有测试通过!但是这个选项对我不起作用,因为。我打算使用硒。
事实证明,当从带有测试的项目启动时,后端由于某种原因不知道wwwroot的实际位置。被对待UseWebRoot()
builder
.ConfigureWebHostDefaults(w =>
{
w.UseUrls(serviceUrl);
w.UseWebRoot(@"..\..\..\..\BlazorApp2\Client\wwwroot");
})
.Build()
.Start();
现在所有测试都通过了,除了WebAssemblyResponcesOk
. 可以理解:文件在不同的目录\BlazorApp2\Client\bin\Debug\netstandard2.1\wwwroot\_framework
但是,如果您添加另一个.UseWebRoot()
,它将简单地取消第一个。
好吧,我通过调试器深入了解了 Asp.Net Core 源代码。
观察到以下情况。_fileProvider
如果您运行后端项目,则为类字段StaticFileMiddleware
分配一个具有以下结构的值
CompositeFileProvider-- ._fileProviders
|
+-- NullFileProvider
|
+-- StaticWebAssetsFileProvider-- .InnerProvider
|
PhysicalFileProvider
|
+-- StaticWebAssetsFileProvider-- .InnerProvider
|
PhysicalFileProvider
一个以源中的 wwwroot 为目标,另一个以PhysicalFileProvider
wwwroot为目标/bin
如果您运行测试,那么它StaticFileMiddleware
_fileProvider
只会PhysicalFileProvider
针对UseWebRoot()
. 如果我们回到没有 的变体UseWebRoot()
,那么我们就完全得到了NullFileProvider
。
现在原图已经很清晰了。但是,仍然不清楚究竟是什么影响了 StaticFileMiddleware 作为文件提供者所获得的内容。使用类型注入将值传递给类构造函数IOptions<StaticFileOptions>
。但是我不明白我在哪里放置断点来捕获这种类型的 DI 注册。
从*.StaticWebAssets.xml 文件
...\Server\bin\Debug\netcoreapp3.1
复制...\NUnitTestProject1\bin\Debug\netcoreapp3.1
添加
UseStaticWebAssets()
到后端启动代码。现在所有测试都通过了,调试器显示注入
CompositeFileProvider
的结构与手动启动后端时几乎相同。在构建事件中设置这些文件的复制
不幸的是,我无法弄清楚如何在测试项目中自动设置这些文件的生成。