In MSTest, How can I verify exact error message using [ExpectedException(typeof(ApplicationException))]

前端 未结 11 1501
南方客
南方客 2020-12-15 16:01

Using MSTest how can I verify the exact error message coming from a test method? I know [ExpectedException(typeof(ApplicationException), error msg)] doesn\'t co

相关标签:
11条回答
  • 2020-12-15 16:34

    This code does it in the async/await scenario:

    Code Reference

    public async static Task AssertThrowsAsync<T>(Task task, string expectedMessage) where T : Exception
    {
        try
        {
            await task;
        }
        catch (Exception ex)
        {
            if (ex is T)
            {
                Assert.AreEqual(expectedMessage, ex.Message);
                return;
            }
    
            Assert.Fail($"Expection exception type: {typeof(T)} Actual type: {ex.GetType()}");
        }
    
        Assert.Fail($"No exception thrown");
    }
    

    Example Usage: Code Reference

        [TestMethod]
        public async Task TestBadRequestThrowsHttpStatusCodeException()
        {
            var mockHttp = new MockHttpMessageHandler();
    
            const HttpStatusCode statusCode = HttpStatusCode.BadRequest;
    
            mockHttp.When("https://restcountries.eu/rest/v2/")
                    .Respond(statusCode, "application/json", JsonConvert.SerializeObject(new { Message = "Test", ErrorCode = 100 }));
    
            var httpClient = mockHttp.ToHttpClient();
    
            var factory = new SingletonHttpClientFactory(httpClient);
    
            var baseUri = new Uri("https://restcountries.eu/rest/v2/");
            var client = new Client(new NewtonsoftSerializationAdapter(), httpClientFactory: factory, baseUri: baseUri, logger: _logger.Object);
    
            await AssertThrowsAsync<HttpStatusException>(client.GetAsync<List<RestCountry>>(), Messages.GetErrorMessageNonSuccess((int)statusCode, baseUri));
        }
    

    This is the equivalent for synchronous situations

    public static void AssertThrows<T>(Action action, string expectedMessage) where T : Exception
    {
        try
        {
            action.Invoke();
        }
        catch (Exception ex)
        {
            if (ex is T)
            {
                Assert.AreEqual(expectedMessage, ex.Message);
                return;
            }
    
            Assert.Fail($"Expection exception type: {typeof(T)} Actual type: {ex.GetType()}");
        }
    
        Assert.Fail($"No exception thrown");
    }
    

    Note: this asserts that the exception inherits from a given type. If you want to check for the specific type you should check for Type equality instead of using the is operator.

    0 讨论(0)
  • 2020-12-15 16:35

    Update: Oops.. see that you want this in MSTest. Sorry. Speed read & Misled by your title.

    Try this extension project from Callum Hibbert and see if it works.

    Old response:

    You can do this with NUnit 2.4 and above. See documentation of ExpectedException here

    [ExpectedException( typeof( ArgumentException), ExpectedMessage="unspecified", MatchType=MessageMatch.Contains )]
    public void TestMethod()
    {
    ...
    

    MatchType can be Exact (default), Contains or Regex.. which pretty much handles the 80% use-case. There is also an advanced exception handler method approach if the verification gets too complex.. never used it personally.. didn't need it yet.

    0 讨论(0)
  • 2020-12-15 16:38

    MbUnit can also do this:

    [Test]
    [Row(ExpectedExceptionMessage="my message")]
    void TestBlah(...
    
    0 讨论(0)
  • 2020-12-15 16:40

    You can create your own ExpectedException attribute where you can Assert the message of the Exception that was thrown.

    Code

    namespace TestProject
    {
        public sealed class MyExpectedException : ExpectedExceptionBaseAttribute
        {
            private Type _expectedExceptionType;
            private string _expectedExceptionMessage;
    
            public MyExpectedException(Type expectedExceptionType)
            {
                _expectedExceptionType = expectedExceptionType;
                _expectedExceptionMessage = string.Empty;
            }
    
            public MyExpectedException(Type expectedExceptionType, string expectedExceptionMessage)
            {
                _expectedExceptionType = expectedExceptionType;
                _expectedExceptionMessage = expectedExceptionMessage;
            }
    
            protected override void Verify(Exception exception)
            {
                Assert.IsNotNull(exception);
    
                Assert.IsInstanceOfType(exception, _expectedExceptionType, "Wrong type of exception was thrown.");
    
                if(!_expectedExceptionMessage.Length.Equals(0))
                {
                    Assert.AreEqual(_expectedExceptionMessage, exception.Message, "Wrong exception message was returned.");
                }
            }
        }
    }
    

    Usage

    [TestMethod]
    [MyExpectedException(typeof(Exception), "Error")]
    public void TestMethod()
    {
        throw new Exception("Error");
    }
    
    0 讨论(0)
  • 2020-12-15 16:44

    MSTest v2 supports Assert.Throws and Assert.ThrowsAsync which returns the captured exception.

    Here is an article on how to upgrade to MSTest v2: https://blogs.msdn.microsoft.com/devops/2017/09/01/upgrade-to-mstest-v2/

    Here is example usage:

    var myObject = new MyObject();
    var ex = Assert.Throws<ArgumentNullException>(() => myObject.Do(null));
    StringAssert.Contains(ex.Message, "Parameter name: myArg");
    
    0 讨论(0)
  • 2020-12-15 16:46

    With MSTest, you can't do this.

    You already know the solution to this problem: assert the message of an exception in a catch block.

    0 讨论(0)
提交回复
热议问题