无法从 NUnit 测试中获取 index.html

Cannot get index.html from a NUnit test

我尝试使用 NUnit 和 Asp.net-core-hosted Blazor WebAssembly 应用程序编写端到端测试。

我使用 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);
}

他们return结果相同Failed 45 ms Expected: OK But was: NotFound

我假设 app.UseStaticFiles(); 没有像我期望的那样工作。这可能是真的吗?如何解决?


因此,当测试项目启动时,后端不知道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 核心源代码。

还有下一个事实。

如果 运行 后端项目,则 class StaticFileMiddleware 中的 _fileProvider 字段将获得具有下一个结构的复杂值:

CompositeFileProvider-- ._fileProviders
                               |                  
                               +-- NullFileProvider
                               |
                               +-- StaticWebAssetsFileProvider-- .InnerProvider
                                                                       |
                                                             PhysicalFileProvider
                               |
                               +-- StaticWebAssetsFileProvider-- .InnerProvider
                                                                       |    
                                                             PhysicalFileProvider

一个PhysicalFileProvider指向源代码中的wwwroot,另一个指向/bin中的wwwroot .

如果 运行 测试,StaticFileMiddleware _fileProvider 得到简单的 PhysicalFileProvider 目标,因为 UseWebRoot() 参数是。如果我 return 到没有 UseWebRoot() 的版本,NullFileProvider 将在那里设置。

现在我可以意识到开始时发生了什么。但我仍然不知道究竟是什么对 StaticFileMiddleware 文件提供程序产生了影响。 class 构造器通过注入 IOptions<StaticFileOptions>.

获取值

捕获这种类型的DI注册应该在哪里设置断点?

根据您收到的回复,即 “NotFound”,我的第一个猜测是为获取该特定文件而创建的路径可能不正确。如果我要调试它,我可能会尝试重载 “MapFallbackToFile” 函数。需要显式路径(绝对或相对)或其他属性的路径。经过一些尝试和尝试,您也许可以找到相应的文件。

另一件可以加快调试过程的事情是,您可以通过编程方式检查当前工作目录,并将其用作构建所需的准确文件路径的参考点。这可以使用以下命令完成:

System.IO.Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);

一个非常常见的错误是我们的程序通常在构建目录中 运行(例如 bin/debug/..)和我们所需的文件(例如 css 或图像)那里没有文件,因此,我们遇到了这样的问题。这是解决此问题的一种方法。

  1. 我已将 *.StaticWebAssets.xml 个文件从 ...\Server\bin\Debug\netcoreapp3.1 复制到 ...\NUnitTestProject1\bin\Debug\netcoreapp3.1

  2. 我已将 UseStaticWebAssets() 添加到后端启动代码中。

    builder
     .ConfigureWebHostDefaults(w =>
     {
         w.UseUrls(serviceUrl);
         w.UseStaticWebAssets();
     })
    .Build()
    .Start();
    

所有测试都通过了。调试器显示 CompositeFileProvider 注入,其结构与后端手动启动时的结构相同...

我已经在构建事件中设置了这些文件的复制

<Target Name="PostBuild" AfterTargets="PostBuildEvent">
    <Exec Command="copy ..\Rest\bin$(ConfigurationName)\net5.0-windows\*.StaticWebAssets.xml .\bin$(ConfigurationName)\net5.0-windows\*.*" />
</Target>

很遗憾,我无法在测试项目中实现自动生成StaticWebAssets.xml。