Reputation: 384
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
Reputation: 384
I've copied *.StaticWebAssets.xml files from ...\Server\bin\Debug\netcoreapp3.1
to ...\NUnitTestProject1\bin\Debug\netcoreapp3.1
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
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