Covers guidance on unit testing Razor Pages:
@DamianEdwards can you assign a dev to write the sample we can use as a basis for the article? Once the sample code is written I can schedule and expedite.
@Rick-Anderson I can take a crack at the sample for this. I'm more familiar with the MVC approach, but I'd like to see how that translates to a RP app. If I do it (and likely run into trouble in the process), it might highlight some pitfalls that need to be covered in the topic. I just need a dev team member on the other end of the Dinosaur Disaster Hotline:tm:.
We're doing this as a ref topic, correct? ... Not rolling it into the RP tutorial but making a standalone topic under mvc/razor-pages for it.
Title? Unit Testing Razor Pages in ASP.NET Core
A few questions:
The unit testing topic is tutorial-ish, and it doesn't do integration testing, which we'll have in this one. I was planning to write this topic as a reference topic with a sample. The other possibility would be adding a step to the RP tutorial (after the File Uploads step). Which way do u want to go? If this is going to be a RP tutorial step, then that answers my Question 2. If it's a ref topic, then Question 2 is still open.
Assuming this will be a ref topic: The current unit testing topic lives over in the .NET Core docs at: https://docs.microsoft.com/dotnet/core/testing/unit-testing-with-dotnet-test. Will this also go over there and link into the TOC over here? If it's a new topic over here, then do you want the link in the TOC below (same level) or under (nested) the current unit testing link?
I suggest building the sample and getting both sample and outline approved together by the dev team. If there's something amiss or missing, they can let us know before the writing effort gets underway. Ok?
@Rick-Anderson @danroth27 @scottaddie @pranavkm @DamianEdwards @javiercn
Razor Pages integration and unit testing in ASP.NET Core
Docs/aspnetcore/testing/
testing/razor-pages-testing
Reference
https://github.com/guardrex/RazorPagesTestingApp
AppDbContext class.TestFixture from the Testing Controllers topic and mostly test the page processing result.Integration testing the app
I'd like to keep the text lean and focused - teach through the sample as much as possible. Where possible, cross-link to the Testing Controllers and Integration testing topics.
PageContext, ActionContext, etc.)? (The sample does create these but doesn't use them in testing.) Or, do you mean performing Mock.Of certain interfaces outside of the RP infrastructure in a typical ASP.NET Core app? ... because if so, I also think that should go elsewhere.@danroth27 can we get this outline and https://github.com/guardrex/RazorPagesTestingApp sample reviewed by EOW? @guardrex is waiting. cc @pranavkm @javiercn and cc @DamianEdwards for the outline
@Eilon @danroth27 can we get this outline and https://github.com/guardrex/RazorPagesTestingApp sample reviewed in the next 3 business days? @guardrex is waiting. cc @pranavkm @javiercn and cc @DamianEdwards for the outline
The outline looks good to me. I left a couple of comments in the commit for the sample (https://github.com/guardrex/RazorPagesTestingApp/commit/0e2470d75ec215d5573ddb9e3b1e1806450eac33#commitcomment-25509962) and doesn't look like they've been addressed.
@pranavkm Oh ... that's strange. I didn't get a GH ping on those, so I had no idea. I'll TAL now.
@pranavkm
These should use await.
Thanks ... yes, of course ... just an oversight. I'll fix 'um.
@Rick-Anderson [@]DamianEdwards looks like he had some ideas about mocking certain services and types used to create page models, and I'd like to make sure that what's in the sample is enough to cover his wishes. I wrote a bit about this in the Philosophical issues section of my comment :point_up:. Should we wait to see if others want to TAL? In the meantime, I'll flip over to the IHostingStartup prep work.
@pranavkm Oh ... I know why I set those up that way now. They're supposed to return a Task so that it can check IsCompletedSuccessfully, then it can use the result.Result to make sure the result is assignable to a List<Message>, get the actual messages, and then proceed to see if they match the expected messages.
Are you saying that this is a bad approach? ... I didn't think it would complete synchronously since it's returning a Task there ...
// Act
var result = db.GetMessagesAsync();
// Assert
Assert.True(result.IsCompletedSuccessfully);
var actualMessages = Assert.IsAssignableFrom<List<Message>>(result.Result);
Assert.True(Utilities.CompareMessages(expectedMessages, actualMessages));
You're suggesting that I should skip the IsCompletedSuccessfully check and just go for ...
// Act
var result = await db.GetMessagesAsync();
// Assert
var actualMessages = Assert.IsAssignableFrom<List<Message>>(result);
Assert.True(Utilities.CompareMessages(expectedMessages, actualMessages));
... after all; if the Task doesn't complete successfully, I think/hope it will fail gracefully (and I'll do a test on that to confirm it if you're saying this would be a better pattern to follow).
You're suggesting that I should skip the IsCompletedSuccessfully check and just go for ...
Yup. User code shouldn't really care about unwrapping the Task. async \ await does this nicely and we should guide them towards using it.
@pranavkm Gotcha, thanks. I'll fix it up.
Most helpful comment
Yup. User code shouldn't really care about unwrapping the Task.
async\awaitdoes this nicely and we should guide them towards using it.