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
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.
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.
MbUnit can also do this:
[Test]
[Row(ExpectedExceptionMessage="my message")]
void TestBlah(...
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");
}
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");
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.