Reputation: 4860
for very specific reasons (explained below), I try to change the testoutcome after the execution of a unit test. I tried the following code:
[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);
}
}
and other variants based on reflection. When I inspect the TestContext object after the execution of the TestCleanup method, the property CurrentTestOutcome is properly set to Inconclusive, but after that, the test still fails.
Do you please have any idea? I'm quite stuck here...
Thanks
Reasons: These are not "real" unit tests, but more "end to end" tests. If some external dependency failed (I know how to detect it), and the test failed, I want to override its outcome to reduce the amount of false negatives.
Upvotes: 2
Views: 1935
Reputation: 86
It may be late, but I managed to find a solution for this.
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");
}
}
}
Upvotes: 1