Here is specific case. I want to test this Assert.ThrowsException<DbException>(() => { MyMethod(0, 100); });
The problem is that exception thrown is SqlException
. Why do I want to test base exception? Because I want a unified test for any of my 3 DB providers. The exception sometimes is OracleException
or MySqlException
. All 3 providers exceptions derive from DbException
Is there a way to test it nicely, using the Microsoft Unit Test framework?
CodePudding user response:
According to the documentation for Assert.ThrowsException this is expected. However, if you're able to use Fluent Assertions, this is in fact very easy to achieve.
Action action = () => MyMethod(0, 100);
action.Should().Throw<DbException>(); // add some more checks
// this would mimic the behavior of Assert.ThrowsException, which should fail.
action.Should().ThrowExactly<DbException>();
See also the tips on improving assertions under Tips/Exceptions.
The alternative would be to use regular try...catch
like in the example below. You need to make sure that you capture all the code path' and don't accidentally succeed:
/// <summary>
/// Catching a base exception class just by using <see cref="Assert"/>.
/// Do not use <see cref="ExpectedExceptionAttribute"/>, since it doesn't
/// provide any type of validation.
/// </summary>
[TestMethod]
public void CatchAderivedExceptionTheAssertWay()
{
try
{
// A test method that throws an exception.
Action action = () => throw new ArgumentNullException("param1");
action();
}
catch (ArgumentException e)
{
// This will catch any exception derived from ArgumentException.
// Do some validation to ensure the right thing is caught,
// like checking the parameter name.
if (!e.ParamName.Equals("param1", StringComparison.Ordinal))
{
Assert.Fail("Reason why the validation failed.");
}
// Otherwise jump out of the test.
return;
}
Assert.Fail("Make sure the test fails, in case the code inside try doesn't throw at all.");
}
For completeness sake, there's also the ExpectedException attribute that can be added to a [TestMethod]
. Due to the lack of validation options I would not recommend using it.
I'll add this question to my list of interview questions. Such a nice example.
CodePudding user response:
Thanks for all the leads, one from @StephanAdler
Considering limitations of given testing framework my sensible solution was this
Exception retEx = null;
try
{
MyMethod(0, 100);;
}
catch (Exception ex)
{
retEx = ex;
}
Assert.IsNotNull(retEx);
Assert.IsInstanceOfType(retEx, typeof(DbException));
Assert.IsInstanceOfType
works perfectly with the base type