Moq / Unit Test Cannot catch exception if not execute code

I have a Unit Test that expects an exception as a return parameter.

If I run the code through Debugger and check various items, it works. If I just run all tests, it doesn't.

The problem must be with the Async method, as if I were removing various Async items, it works like expexted. (I think it's a matter of time)

my unit test:

  [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)

    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 redo this test to catch excpetion when running async. And as a bonus question, can I modify my unit test so that I can check for specific exceptions and not an Aggregate Exception?

+3


source to share


1 answer


The reason your test runs asynchronous code that is executed after the assert has already been run (or not). Using the debugger only gives the asynchronous code more time to work. To test your code, all you have to do is chnage the return type of your MTest for the task, and add await for the appropriate 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;
}  

      

+1


source







All Articles