Reputation: 1616
I have a Unit Test, that is expecting an Exception as the return parameter.
If I run the code through the Debugger, and inspect various elements it works. If I just run all th tests, it doesn't.
The issue has to be something to do with the fact that the method is Async, as if I remove the various Async elements it works as expexted. (I guess its a timing issue)
my unit test is;
[TestMethod]
[ExpectedException(typeof(System.AggregateException))]
public void Service_GetDoc_ThrowsExceptionIfNull()
{
var nullRepository = new Mock<CCLDomainLogic.Repositories.DocRepository>();
IDD emptyDoc = null;
nullRepository
.Setup<Task<CCLDomainLogic.DomainModels.Doc>>
(x => x.GetDocAsync(It.IsAny<int>()))
.Returns(() => Task<CCLDomainLogic.DomainModels.Doc>.Factory.StartNew(() => emptyDoc));
DocService s = new DocService(nullRepository.Object);
var foo = s.GetDocAsync(1).Result;
}
And the code (abbreviated is)
public async Task<Doc> GetDocAsync(int id)
{
Stopwatch timespan = Stopwatch.StartNew();
try
{
...
{
var t = await Task.Run(() => _repository.GetDocAsync(id));
...
}
timespan.Stop();
if (t == null)
{
throw new ArgumentNullException("DocService.GetDocAsync returned Null Document");
}
}
catch (Exception e)
{
throw new Exception("Error in DocService.GetDocAsync", e);
}
}
So how do I rework this test to catch the excpetion when running async. And as a bonus question, can I modify my unit test so I can check for specific exceptions, not the Aggregate Exception?
Upvotes: 4
Views: 1687
Reputation: 30790
The reason that your test runs async code that executes after the assert has already run (or not). Using the debugger only give the async code more time to workl. In order to test your code all you have to do is chnage the return type of your MTest to Task and add await to thje relevant call:
[TestMethod]
[ExpectedException(typeof(System.AggregateException))]
public async Task Service_GetDoc_ThrowsExceptionIfNull()
{
var nullRepository = new Mock<CCLDomainLogic.Repositories.DocRepository>();
IDD emptyDoc = null;
nullRepository
.Setup<Task<CCLDomainLogic.DomainModels.Doc>>(x => x.GetDocAsync(It.IsAny<int>()))
.Returns(() => Task<CCLDomainLogic.DomainModels.Doc>.Factory.StartNew(() => emptyDoc));
DocService s = new DocService(nullRepository.Object);
var foo = await s.GetDocAsync(1).Result;
}
Upvotes: 1