I need to have a logged in user for each of my unit tests, which forces me to do an async call (the login) in my test SetUp
.
I can't find a way to make this work, I either get null pointer exceptions, or invalid signatures for setup.
public async void SetUp() {}
This makes all my test fail with my objects probably because I'm not logged in.
public async Task SetUp() {}
Makes all my test ignored because the setup has an invalid signature.
And I would like not to have to copy my X lines of setup in each test, since they're all exactly the same and... that's what the setup is for.
What am I missing ? this appears like a trivial problem.
Here is what I have now, for the sake of showing something
CreateTicketViewModel _viewModel;
[SetUp()]
public async void SetUp() //I have tried using Task instead of void
{
IUserService userService = Dependency.Instance.Resolve<IUserService>();
await userService.LoginAsync(this.UserName, this.Password);
_viewModel = Dependency.Instance.Resolve<CreateTicketViewModel>();
}
[TearDown()]
public void TearDown()
{
_viewModel = null; // I have tried removing this
}
[Test()]
public void Initialization()
{
// If I put what's in SetUp here and add "async" before void,
// it works just fine
Assert.IsNotNull(_viewModel);
Assert.IsNotNull(_viewModel.Ticket);
}
Depending on the unit test framework you use async
setup may not be handled correctly by the framework.
in NUnits case I think it doesn't support yet async Setup methods.
So what you should do in your Setup is to just wait synchronously for the Login to complete:
userService.LoginAsync(this.UserName, this.Password).Wait()
;
EDIT: looks like it's an open issue https://github.com/nunit/nunit/issues/60
It's the case for MSTests also.
Could you not just make your SetUp method not async at all and write this?
new Task(() => userService.LoginAsync(this.UserName, this.Password)).RunSynchronously()
Async Setups are not supported but async test methods are supported. You can make your test methods async instead of setup method.
[TestFixture]
public class AsyncSetupTest
{
private Task<CreateTicketViewModel> viewModelTask;
[SetUp()]
public void SetUp()
{
viewModelTask = Task.Run(async () =>
{
IUserService userService = Dependency.Instance.Resolve<IUserService>();
await userService.LoginAsync(this.UserName, this.Password);
return Dependency.Instance.Resolve<CreateTicketViewModel>();
});
}
[Test()]
public async Task Initialization()
{
CreateTicketViewModel viewModel = await viewModelTask;
Assert.IsNotNull(viewModel);
Assert.IsNotNull(viewModel.Ticket);
}
}
Idea is, instead of getting all the setup work done in Setup
method, we create a Task
representing the completion of setup and awaiting it in the Test
method.
This way you're not repeating all the setup logic. But just extracting the ViewModel from Task
inside all test methods.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With