The idea is you break testing down into little pieces that test different parts of your application. Then have MSTest test all those pieces.
An MS Test project contains a series of class files. There’s an initialize test section per class file, and then a series of functions which you write to perform tests.
In my case I setup class per business object, and then a method for each method in the business object class.
standard patterns
A test class may have a stage/tear down process.
Each testing method might have 3 sections: the commonly referred to as Arrange / Act / Assert. (For me the pattern is good, but the terms are bad. I tend to thing something along the line of setup test / perform the test / analyse results.)
namespace Notes.API.Tests { \[TestClass\] public classNoteControllerTests { private NoteController _controller; private Mock<INoteService> _mockNoteService; \[TestInitialize\] public voidSetup() { // Arrange
// here is some sample data var noteDtoList = new List<NoteDto> { new NoteDto { ApplicationKey = "MyApp", ApplicationSubKey = "Notes", CompanyKey = "Test", Note = "This is a new note - 1", Who = "John Doe" }, new NoteDto { ApplicationKey = "MyApp", ApplicationSubKey = "Notes", CompanyKey = "Test", Note = "This is a new note 2", Who = "John Doe" }, // Add more NoteDto instances as needed };
result.WasSuccessful = true;
// here is a mock object - a service mock _mockNoteService = new Mock<INoteService>();
// you would add a .setup ().returnAsync() per function you are emulating _mockNoteService .Setup(service => service.GetAllNotesAsync(It.IsAny<string>(), It.IsAny<string>(), It.IsAny<string>())) .ReturnsAsync(result);
// this command creates your API class, with a fake service layer. _controller = new NoteController(_mockNoteService.Object); }
// Act // this calls the API, and returns information in an aTaskActionResult object. that object will be studied. IActionResult aTaskActionResult = await _controller.GetNotes(companyKey, applicationKey, applicationSubKey);
// Assert // here is our test cases
// an Assert function performs a test. In our case we want to make sure we got ack an OkObjectResult type of object Assert.IsInstanceOfType(aTaskActionResult, typeof(OkObjectResult), "1. Not an OkObjectResult. What you have is a " + aTaskActionResult.GetType()); // // Assert Statements are tests. // If the test passes move on to the next statement. // If the test fails then send a message to MS Test. // Then MSTest will exit this method and start testing the following method. //
// if we did return an OkObjectResult, then we'll instantiate the object as an OkObjectResult var okResult = (OkObjectResult)aTaskActionResult;
// and then pull the model out of that object (which incidenttly is a baseResult object with a list of note objects) IResult<List<NoteDto>> aModel = (IResult<List<NoteDto>>)okResult.Value; // This will give you the model object
// we'll test that class to make sure it is what we think it is. Assert.IsInstanceOfType(aModel, typeof(IResult<List<NoteDto>>), "2. Not a <IResult<List<NoteDto>>> it's a " + okResult.Value.GetType());
// the testing goes on and on. var resultValue = (IResult<List<NoteDto>>)okResult.Value;
Assert.IsTrue(resultValue.WasSuccessful, "3. resultValue.WasSuccessful was not True"); // Add additional assertions based on the expected result }
// // after this test is coded, then we create another test for another API // method that should be tested. // \[TestMethod\] public async Task T010_GetNote_ValidInput_ReturnsOkResult() { }
// and so on \[TestMethod\] public async Task T015_CreateNote_ValidInput_ReturnsOkResult() { } } }
Opinions
Today (May 16, 2024) I am a MSTest rookie. I’ve noticed a few things which could be problems with me, or problems with the program that could be fixed the day after I publish this paper.
Debug doesn’t work, so I cannot pause the test and study results. This forces me to add messages to each assert statement to better track down where it fails in code. - bad.
Sometimes the code fails, not in an assert statement but outsie that, in which case I do not know of a nicer way to get a message to the MS Test UI. - bad.
As I am developing the test case / and similtaneously debugging my API, if I rerun a test (without saving my code changes), it will save the code changes, recompile, and run the latest version of that code - good.