Nunit async test exception assertion

后端 未结 6 1686
感情败类
感情败类 2020-12-29 18:37

[Edit (May 2020)] - This issue has been reportedly addressed in newer releases of NUnit. Please see Nunit.ThrowsAsync. (Ref this answer, thanks @James-Ross)

6条回答
  •  萌比男神i
    2020-12-29 19:26

    This blog talks about problems similar to mine.

    I followed the recommendation proposed there, and have a test like this -

        [Test]
        public void ShouldThrow404WhenNotFound()
        {
            var mockUserRepository = new Mock();
            mockUserRepository.Setup(x => x.GetByUserName(It.IsAny())).Returns(default(User));
            var userController = new UserController(mockUserRepository.Object) { Request = new HttpRequestMessage() };
    
            var aggregateException = Assert.Throws(() => userController.Get("foo").Wait());
            var httpResponseException = aggregateException.InnerExceptions
                .FirstOrDefault(x => x.GetType() == typeof(HttpResponseException)) as HttpResponseException;
    
            Assert.That(httpResponseException, Is.Not.Null);
            Assert.That(httpResponseException.Response.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
        }
    

    I am not too pleased with it, but this works.

    EDIT 1

    Inspired by @StephenCleary, I added a static helper class that does the asserts that I am looking for. It looks like this -

    public static class AssertEx
    {
        public static async Task ThrowsAsync(Func func) where TException : class
        {
            await ThrowsAsync(func, exception => { });
        } 
    
        public static async Task ThrowsAsync(Func func, Action action) where TException : class
        {
            var exception = default(TException);
            var expected = typeof(TException);
            Type actual = null;
            try
            {
                await func();
            }
            catch (Exception e)
            {
                exception = e as TException;
                actual = e.GetType();
            }
    
            Assert.AreEqual(expected, actual);
            action(exception);
        }
    }
    

    I can now have a test like -

        [Test]
        public async void ShouldThrow404WhenNotFound()
        {
            var mockUserRepository = new Mock();
            mockUserRepository.Setup(x => x.GetByUserName(It.IsAny())).Returns(default(User));
            var userController = new UserController(mockUserRepository.Object) { Request = new HttpRequestMessage() };
    
            Action asserts = exception => Assert.That(exception.Response.StatusCode, Is.EqualTo(HttpStatusCode.NotFound));
            await AssertEx.ThrowsAsync(() => userController.Get("foo"), asserts);
        }
    

提交回复
热议问题