我正在使用Nunit为C#项目编写单元测试。
我正在尝试使用TestCaseSource
属性使用不同的数据多次运行单个测试。
我在其他地方这样做没有任何问题,但现在我发现我第一次运行我的测试,代码通过。下一次,它没有。使用一些Console.WriteLine
语句,我可以看到测试数据每次都不同。
用于生成数据的方法是测试类的内部方法,不是静态的,并且每次测试都会从头开始生成所有必需的依赖项。
-
我有一个假类,它保存一个值队列,以便在调用给定函数时返回。为每个测试创建一个新类。
但是,如果第一次运行测试,它会耗尽队列,下次运行时,不会找到任何数据。当然这应该每次都重新生成?
-
每次运行测试时,就好像Nunit没有调用TestCaseSource
属性指定的方法 - 只有在首次加载项目时。
这是预期的吗?有解决方法吗?
编辑:
好的,这是一个非常基本的例子,如下:
[TestFixture]
public class Tests
{
public interface IEntry
{
object Read();
}
[TestCaseSource("TestData")]
public void Test(Mock<IEntry> entry)
{
object o = entry.Object.Read();
object o2 = entry.Object.Read();
}
public System.Collections.IEnumerable TestData()
{
var entry = new Mock<IEntry>();
int call = 0;
entry.Setup(x => x.Read()).Returns(() =>
{
Console.WriteLine(call);
return null;
}).Callback(() =>
{
call++;
});
yield return new TestCaseData(entry);
}
}
如果你在Nunit中观察测试输出,它应该总是显示0,然后是1.在这种情况下,每次运行测试时它都会递增。即第二次运行:2和3,第三次运行:4和5,等等。
如果您将TestData
代码移至Test
,则每次都会返回正确的值。
答案 0 :(得分:0)
我假设您正在使用NUnit GUI运行器?
您所看到的是(我相信,我在NUnit源代码中无法轻易找到确认信息)是对测试运行器的优化。不是在每次测试运行时重新创建TestCaseSource
属性提供的值,而是在测试中的程序集发生更改时才会这样做。
如果您更改代码以删除Moq依赖项,则会更清楚:
[TestFixture]
public class SampleTests
{
[TestCaseSource("TestData")]
public void Test(CallTracker callTracker)
{
callTracker.Call++;
callTracker.Call++;
}
public IEnumerable TestData()
{
yield return new TestCaseData(new CallTracker());
}
public class CallTracker
{
int call;
public int Call
{
get
{
return call;
}
set
{
call = value;
Console.WriteLine(call);
}
}
}
}
这会产生与代码相同的行为。每当评估CallTracker
时,TestCaseSource
都会重新创建,但由于调用计数不断增加,测试运行器必须重新生成相同的实例(因为我假设是性能原因)。
Visual Studio 中的Resharper测试运行器不会出现此行为;它总是显示1
和2
重复运行而不重新编译。这可能是为什么开始运行测试比NUnit GUI运行器慢的原因。同样,NUnit控制台不会出现这种行为,因为它总是冷却。