我有一个单元测试:
[Test]
[TestCaseSource(typeof(AllExampleEnumValues))]
public void GivenSth_WhenSth_ThenSth(ExampleEnum enumValue)
{
// Given
var givenState = BaseClassProperty; // property from fixture's base class
systemUnderTest.SetSomeState(givenState);
// When
var result = systemUnderTest.AnswerAQuestion(
"What's the answer to"
+ " the Ultimate Question of Life,"
+ " the Universe,"
+ " and Everything?");
// Then
Assert.That(result, Is.EqualTo(42));
}
其中AllExampleEnumValues
如下:
public class AllGranularities : IEnumerable
{
public IEnumerator GetEnumerator()
{
return Enum
.GetValues(typeof(ExampleEnum))
.Cast<ExampleEnum>()
.Select(ee => new object[] { ee })
.GetEnumerator();
}
}
在基类中我有:
protected int BaseClassProperty
{
get
{
return //depending on enumValue
}
}
如何在运行期间enumValue
内获取BaseClassProperty
参数的当前值,而不将其更改为函数并将enumValue
作为参数传递?
我知道我可以以某种方式走到堆栈框架并从那里读取它(不,实际上,我不能:How can I get the values of the parameters of a calling method?),但也许有更优雅的解决方案?
我需要这个来改进测试&#39;可读性 - enumValue
影响阅读结果的事实BaseClassProperty
隐含地不会降低可读性,因为在我的域中,这种依赖性对每个人都是显而易见的。
我一直在研究TextContext
类,但似乎在这种情况下没有任何用处。正如评论中所提到的,值存在于测试的名称中 - 但是这里不能接受从字符串中解析值,因为有时我们使用多个参数和通用测试用例。
另一条线索导致使用IApplyToTest
属性。但是,这需要将此属性应用于每个测试。
最后,另一条路径导致使用ITestAction
,我可以访问ITest
接口,该接口提供TestMethod
个实例。它有Arguments
属性!不幸的是 - 它是私人的。
答案 0 :(得分:0)
我设法创建了以下解决方法:
[AttributeUsage(AttributeTargets.Class)]
public class TrackEnumValueActionAttribute : Attribute, ITestAction
{
public ActionTargets Targets
{
get
{
return ActionTargets.Test;
}
}
public void AfterTest(ITest test)
{
}
public void BeforeTest(ITest test)
{
if (!(test.Fixture is ICurrentExampleEnumValueHolder))
{
return;
}
var arguments = GetArgumentsFromTestMethodOrNull(test);
if (arguments == null)
{
return;
}
var eumValue = GetEnumValueFromArgumentsOrNull<ExampleEnum>(arguments);
(test.Fixture as ICurrentExampleEnumValueHolder).CurrentEnumValue = enumValue;
}
private object[] GetArgumentsFromTestMethodOrNull(ITest test)
{
return test
.GetType()
.GetProperty("Arguments", System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)
?.GetValue(test) as object[];
}
private T? GetEnumValueFromArgumentsOrNull<T>(object[] arguments) where T : struct
{
return arguments
.Where(a => a.GetType().Equals(typeof(T)))
.Select(a => (T?)a)
.FirstOrDefault();
}
}
将此属性应用于我的fixture的基类,并实现ICurrentExampleEnumValueHolder
接口可以解决问题 - 我的属性(存在于接口中)的值具有取决于测试方法调用参数的值。 / p>
不幸的是,NUnit中Arguments
类的TestMethod
属性是内部的,因此丑陋的反射解决方法。我已就此问题发布了一个问题:https://github.com/nunit/nunit/issues/2079