3per
3per

Reputation: 384

Cannot get index.html from a NUnit test

I try to write end-end test with NUnit and Asp.net-core-hosted Blazor WebAssembly Application.

I created a new project with 3.1.7 template. Then I just add a NUnit project and write simple test.

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

I've changed nothing else.

I get the next result

Test                        Duration  Error Message
HomePageResponcesOk Failed  45 ms     Expected: OK   But was:  NotFound 
ApiResponcesOk      Passed  364 ms      

What I do wrong?

I can point out, that it works fine in more early Blazor WebAssembly versions.


I have added yet two other tests

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

They return the same result Failed 45 ms Expected: OK But was: NotFound.

I assume that app.UseStaticFiles(); does not work how I expect. May it be true? How fix it?


So, when test project started, the backend does not know where wwwroot is. It can be fixed with UseWebRoot().

builder
    .ConfigureWebHostDefaults(w =>
    {
        w.UseUrls(serviceUrl);
        w.UseWebRoot(@"..\..\..\..\BlazorApp2\Client\wwwroot");
    })
   .Build()
   .Start();

All tests passed successfully, except WebAssemblyResponcesOk(). It is beacause of the file placed in another directory \BlazorApp2\Client\bin\Debug\netstandard2.1\wwwroot\_framework. If I add second .UseWebRoot() then just first one be cancelled.


Ok, I dive into ASP.Net Core source code with the debugger.

There are next facts.

If run backend project, then _fileProvider field in the class StaticFileMiddleware gets a complex value with next structure:

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

OnePhysicalFileProvider is targeted to wwwroot in the source code, another to wwwroot in the /bin.

If run the tests, StaticFileMiddleware _fileProvider gets simple PhysicalFileProvider target as UseWebRoot() argument is. If I return to version without UseWebRoot(), NullFileProvider will be set there.

Now I can realized what was hapenning on the start. But I still don't know what exactly has an effect on a StaticFileMiddleware file provider. The class construcor gets the value with a injection of IOptions<StaticFileOptions>.

Where should I set a breakpoint for catching DI registration of this type?

Upvotes: 3

Views: 472

Answers (2)

3per
3per

Reputation: 384

  1. I've copied *.StaticWebAssets.xml files from ...\Server\bin\Debug\netcoreapp3.1 to ...\NUnitTestProject1\bin\Debug\netcoreapp3.1

  2. I've added UseStaticWebAssets() into backend launch code.

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

All of the tests passed. Debugger shows CompositeFileProvider injection with same structure as when backend launched manual...

I've setup copying of these files in build events

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

It a pity, that I cannot realize how implement auto-generation StaticWebAssets.xml in a test project.

Upvotes: 0

Mikaal Anwar
Mikaal Anwar

Reputation: 1791

Based on your received response i.e. “NotFound”, my first guess would be that the path being created for fetching that particular file might be incorrect. If I was to debug that I’d probably try a few overloads of the “MapFallbackToFile” function. Ones that require an explicit path (absolute or relative) or other properties. After a bit of hit and trial, you might be able to find the respective file.

Another thing you can do to speed up the debugging process is that you can programmatically check the current working directory and use that as a point of reference to construct the accurate file path needed. This can be done using the following command:

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

A very commonly faced error is that often our program is running in the build directory (e.g bin/debug/..) and our required file (e.g. css or image) file is not present there, hence, we encounter such issues. This is one way to go about solving this problem.

Upvotes: 2

Related Questions