简体   繁体   English

如何使用 Microsoft 单元测试框架测试基本 class 异常实现的 Assert?

[英]How to test Assert for base class exception implementation using Microsoft Unit testing framework?

Here is specific case.这里是具体案例。 I want to test this Assert.ThrowsException<DbException>(() => { MyMethod(0, 100); });我想测试这个Assert.ThrowsException<DbException>(() => { MyMethod(0, 100); });

The problem is that exception thrown is SqlException .问题是抛出的异常是SqlException Why do I want to test base exception?为什么要测试基本异常? Because I want a unified test for any of my 3 DB providers.因为我想对我的 3 个数据库提供程序中的任何一个进行统一测试。 The exception sometimes is OracleException or MySqlException .有时异常是OracleExceptionMySqlException All 3 providers exceptions derive from DbException所有 3 个提供程序异常都派生自DbException

Is there a way to test it nicely, using the Microsoft Unit Test framework?有没有办法很好地测试它,使用 Microsoft 单元测试框架?

According to the documentation for Assert.ThrowsException this is expected.根据Assert.ThrowsException的文档,这是预期的。 However, if you're able to use Fluent Assertions , this is in fact very easy to achieve.但是,如果您能够使用Fluent Assertions ,这实际上很容易实现。

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 .另请参阅Tips/Exceptions下有关改进断言的技巧。

The alternative would be to use regular try...catch like in the example below.另一种方法是使用常规的try...catch ,如下例所示。 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] .为了完整起见,还有可以添加到[TestMethod]ExpectedException属性。 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.这样一个很好的例子。

Thanks for all the leads, one from @StephanAdler感谢所有线索,来自@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 Assert.IsInstanceOfType与基本类型完美配合

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM