Reputation: 226
I have a ASP.NET core (.NET Framework) project set up with Entity Framework for working with my database. I have created a seperate project for tests in my solution.
How will I go about writing unit tests for endpoints like 'register', 'signin', etc. ?
Here is a snippet of my RegisterUser endpoint.
public async Task<IActionResult> RegisterUser(string email, string name, string password)
{
var user = new User { UserName = email, Email = email, Name = name };
IdentityResult resultCreate = null;
if (email.EndsWith("@stud.ntnu.no") || email.EndsWith("@ntnu.no"))
{
// Student or teacher?
var role = (email.EndsWith("@stud.ntnu.no") ? "Student" : "Teacher");
resultCreate = await _userManager.CreateAsync(user, password);
if (resultCreate.Succeeded)
{
// Add role
var resultRole = await _userManager.AddToRoleAsync(user, role);
if (resultRole.Succeeded)
{
// Sign in
await _signInManager.SignInAsync(user, true);
return Ok();
}
}
}
// Error
return StatusCode(400, resultCreate?.Errors);
}
Upvotes: 0
Views: 312
Reputation: 61993
Judging by the comments below the original post, the actual question appears to be "How can I avoid persisting unit test data?"
There is a number of ways you can go about it:
Unit tests should test only one thing, and everything else should be mocked. So, mock your _userManager
and your _signInManager
. Since they are mocked, they don't persist anything, so the avoidance of test data persistence comes for free. In my experience this is a rather retarded way for testing almost anything, and I strongly advise against it.
The rest of the approaches begin with the realization that you are not actually writing unit tests, you are writing integration tests, because you are testing your application logic in integration with your database layer.
Use an in-memory-database, and have each test create a new database which is thrown away at the end of the test. Unfortunately, this means restarting your entire database layer, and if you are using something heavyweight like an ORM, it means that a huge performance overhead will be added to each test.
Have each test method start a transaction, and once it is done, roll it back. This is the preferred way of doing things. Under certain conditions you might even be able to annotate your test methods with @Transactional
, and if all the rest of the required magic is right, then transactions might be taken care of for you. Then again, with annotations you never know whether something will really happen, and in this case if the transactionality does not happen then you are ruining your database, so my preference is to stay clear from @Transactional
and code my transaction-begins and transaction-rollbacks myself.
Upvotes: 2