c#单元测试变更测试结果

时间:2014-11-29 15:07:01

标签: c# unit-testing mstest

由于非常具体的原因(如下所述),我尝试在执行单元测试后更改测试结果。 我尝试了以下代码:

[TestClass]
public class UnitTest1
{
    public TestContext TestContext { get; set; }

    [TestMethod]
    public void TestMethod1()
    {
        Assert.Fail();
    }

    [TestCleanup]
    public void Cleanup()
    {
        TestContext.GetType()
            .GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
            .First((fieldInfo) => fieldInfo.Name.ToLowerInvariant().Contains("outcome"))
            .SetValue(TestContext, UnitTestOutcome.Inconclusive);
    }
}

和其他基于反射的变体。当我在执行TestCleanup方法后检查TestContext对象时,属性CurrentTestOutcome被正确设置为Inconclusive,但在此之后,测试仍然失败。

你有什么想法吗?我完全被困在这里......

由于

理由: 这些不是真实的"单元测试,但更多"端到端"试验。如果某些外部依赖失败(我知道如何检测它),并且测试失败,我想覆盖其结果以减少错误否定的数量。

1 个答案:

答案 0 :(得分:1)

可能会迟到,但我设法为此找到了解决方案。

    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Microsoft.VisualStudio.TestTools.Common;
    using System;
    using System.Linq;
    using System.Reflection;

    namespace ServiceTests
    {
        [TestClass]
        public class Test
        {
            public TestContext TestContext { get; set; }

            [TestCleanup()]
            public void MyTestCleanup()
            {
                if (TestContext.CurrentTestOutcome == UnitTestOutcome.Failed)
            {
                Type classType = this.GetType(TestContext.FullyQualifiedTestClassName);
                if (classType != null)
                {
                    object instance = Activator.CreateInstance(classType);
                    MethodInfo method = classType.GetMethod(TestContext.TestName);
                    try
                    {
                        method.Invoke(instance, null);

                        // if the above call does not throw exception it passes for sure, 
                        // so changing the previous status and message is needed to be done.
                        FieldInfo resultField = TestContext.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
                            .Where(x => x.Name.Contains("m_currentResult")).First();

                        object currentTestResult = resultField.GetValue(TestContext);
                        FieldInfo outcomeProperty = currentTestResult.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
                            .Where(x => x.Name.Equals("m_outcome")).First();
                        outcomeProperty.SetValue(currentTestResult, TestOutcome.Passed);

                        FieldInfo errorInfoProperty = currentTestResult.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
                            .Where(x => x.Name.Equals("m_errorInfo")).First();

                        object errorInfoValue = errorInfoProperty.GetValue(currentTestResult);
                        FieldInfo messageProperty = errorInfoValue.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
                            .Where(x => x.Name.Equals("m_message")).First();
                        messageProperty.SetValue(errorInfoValue, "Passed.");

                        FieldInfo stackTraceProperty = errorInfoValue.GetType().GetFields(BindingFlags.Instance | BindingFlags.NonPublic)
                            .Where(x => x.Name.Equals("m_stackTrace")).First();
                        stackTraceProperty.SetValue(errorInfoValue, null);
                    }
                    catch
                    {
                    }
                }
            }
            }

            private static int i = 0;
            [TestMethod]
            public void TMethod()
            {
                i++;
                if (i == 1)
                    Assert.Fail("Failed");
            }
        }
    }