(MSTest)扩展ExpectedExceptionBaseAttribute隐藏测试失败说明

时间:2013-11-29 11:25:32

标签: c# unit-testing exception visual-studio-2012 mstest

运行此测试时:

    [TestMethod]
    [ExpectedException(typeof(SpecialException))]
    public void Test1()
    {
        throw new NotImplementedException();
    }

Visual Studio告诉我它失败的原因:

  

测试方法[...]。测试1投掷   异常System.NotImplementedException,但异常   [...]。期待SpecialException。例外   message:System.NotImplementedException:方法或操作是   没有实施。

但是当我尝试扩展ExpectedExceptionBaseAttribute(期望SpecialException中的错误代码)时:

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = true)]
class ExpectedSpecialException : ExpectedExceptionBaseAttribute
{
    protected override void Verify(Exception exception)
    {
        SpecialException se = exception as SpecialException;

        if (se == null)
        {
            RethrowIfAssertException(exception);

            throw new Exception("SpecialException was expected but test method threw another one");
        }
    }
}

并使用它:

    [TestMethod]
    [ExpectedSpecialException]
    public void Test1()
    {
        throw new NotImplementedException();
    }

VS产生了一条信息量不大的消息:

  

调用目标抛出了异常。

我在互联网上找到的扩展ExpectedExceptionBaseAttribute的所有示例(123)都尝试提供有关抛出异常失败的更多信息,但没有结果。

我做错了吗?有没有办法提供有关此类失败测试的更多信息?

3 个答案:

答案 0 :(得分:3)

我认为您在问题中引用的任何帖子都没有正确实现自定义的ExpectedException属性。我不是说它们不是有效的解决方案,我说它们解决了不同的问题。我认为你所经历的是一个不同的问题,这些问题都没有得到解决。

由于 null TestContext,您似乎没有收到完整的错误消息。

您可以通过查看ExpectedExceptionAttribute的实施来验证这一点。 您可以使用反射器,您可以看到它在内部使用TestContext。

如果你看一下 ExpectedExceptionBaseAttribute 的实现

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false,
Inherited = true)]
public abstract class ExpectedExceptionBaseAttribute : Attribute
{
     protected internal TestContext TestContext { get; internal set; }

TestContext在运行时设置内部,不能注入 ExpectedSpecialException 属性。 MSTest的 ExpectedExceptionAttribute 可以访问由测试运行器内部设置的 TestContext 。需要注意的是,由于MSTest缺乏可扩展性,我们无法真正根据需要访问和设置TestContext。

不确定这会有所帮助,但您可以使用像this这样的方法自定义异常和引发异常的位置。我认为这是一种更好的方法。

答案 1 :(得分:0)

为了它的价值,我通过仅将断言异常传递给基础RethrowIfAssertException函数来解决这个问题:

protected override void Verify(Exception exception)
{
    if (exception is UnitTestAssertException)
    {
        RethrowIfAssertException(exception);
    }

    try
    {
         Assert.IsInstanceOfType<SpecialException>(exception);
    }
    catch (AssertionFailedException ex)
    {
         RethrowIfAssertException(ex);
    }
}

答案 2 :(得分:0)

经过我自己的研究以找到解决方案,我发现对于版本11(VS2012),它似乎是VSTestIntegration dll中的错误。

Microsoft.VisualStudio.TestPlatform.MSTestFramework.TestMethodRunner.HandleMethodException方法使用反射调用调用ExpectedExceptionBaseAttribute以外的继承的ExpectedExceptionAttribute类。根据{{​​3}},如果“被调用的方法或构造函数引发异常”,则返回TargetInvocationException,真正的异常在InnerException中。

不幸的是,HandleMethodException不会通过显示来检查消息的内部异常

  

调用的目标已引发异常。

此问题已在版本14(VS2017)中修复,并且可能早于此版本,但我没有要对其进行验证。 dll位于

  

'C:\ Program Files(x86)\ Microsoft Visual Studio [version] \ Common7 \ IDE \ CommonExtensions \ Microsoft \ TestWindow \ Extensions \ Microsoft.VisualStudio.TestPlatform.Extensions.VSTestIntegration.dll

感谢@ Jon-Skeet购买了MS documentation