- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我在计算两次 C# Xunit 测试中来自静态类的计算数据时遇到了一些问题。
这将用于的实际生产代码要复杂得多,但后面的代码足以展示我所看到的问题。
在下面的代码中,我有一个随机生成的、延迟加载的 int
种子从当前时间开始。
我在这里测试的只是这个属性等于它自己。我通过 MemberData
函数将属性的值插入到测试中。
由于属性应该只被初始化一次,我希望这个测试应该总是通过。我希望静态字段会在 RandomIntMemberData
函数运行时被初始化,并且再也不会。
但是,这个测试总是失败。插入到测试中的值和测试的值总是不同的。
此外,如果我调试,我只会看到初始化代码被命中一次。即,被测试的值。我从未见过被测试值的初始化。
我是不是误解了什么,或者 Xunit 在幕后做了一些奇怪的魔术来设置它的输入数据,然后在实际运行测试时再次初始化该值?
重现错误的最少代码
public static class TestRandoIntStaticClass
{
private static readonly Lazy<int> LazyRandomInt = new Lazy<int>(() =>
{
// lazily initialize a random interger seeded off of the current time
// according to readings, this should happen only once
return new Random((int) DateTime.Now.Ticks).Next();
});
// according to readings, this should be a thread safe operation
public static int RandomInt => LazyRandomInt.Value;
}
测试
public class TestClass
{
public static IEnumerable<object[]> RandomIntMemberData()
{
var randomInt = new List<object[]>
{
new object[] {TestRandoIntStaticClass.RandomInt},
};
return randomInt as IEnumerable<object[]>;
}
[Theory]
[MemberData(nameof(RandomIntMemberData))]
public void RandoTest(int rando)
{
// these two ought to be equal if TestRandoIntStaticClass.RandomInt is only initialized once
Assert.True(rando == TestRandoIntStaticClass.RandomInt,
$"{nameof(rando)} = {rando} but {nameof(TestRandoIntStaticClass.RandomInt)} = {TestRandoIntStaticClass.RandomInt}");
}
}
最佳答案
在测试发现时,Visual Studio Xunit 控制台运行器创建 AppDomain,其中包含所有属性(如 MemberData、ClassData、DataAttribute)的测试数据,因此所有数据在构建后仅保存在内存中(这也是 XUnit 要求类可序列化的原因).
我们可以通过向您的方法添加一个简单的记录器来验证这一点:
namespace XUnitTestProject1
{
public class TestClass
{
public static IEnumerable<object[]> RandomIntMemberData()
{
var randomInt = new List<object[]>
{
new object[]
{TestRandoIntStaticClass.RandomInt},
};
return randomInt;
}
[Theory]
[MemberData(nameof(RandomIntMemberData))]
public void RandoTest(int rando)
{
// these two ought to be equal if TestRandoIntStaticClass.RandomInt is only initialized once
Assert.True(rando == TestRandoIntStaticClass.RandomInt, $"{nameof(rando)} = {rando} but {nameof(TestRandoIntStaticClass.RandomInt)} = {TestRandoIntStaticClass.RandomInt}");
}
}
public static class TestRandoIntStaticClass
{
private static readonly Lazy<int> LazyRandomInt = new Lazy<int>(() =>
{ // lazily initialize a random interger seeded off of the current time
// according to readings, this should happen only once
var randomValue = new Random((int) DateTime.Now.Ticks).Next();
File.AppendAllText(@"D:\var\log.txt", $"Call TestRandoIntStaticClass {randomValue}; ThreadId {Thread.CurrentThread.ManagedThreadId} " + Environment.NewLine);
return randomValue;
});
public static int RandomInt => LazyRandomInt.Value; // according to readings, this should be a thread safe operation
}
}
结果我们在日志中看到:
> Call TestRandoIntStaticClass 1846311153; ThreadId 11
> Call TestRandoIntStaticClass 1007825738; ThreadId 14
并在测试执行结果中
rando = 1846311153 but RandomInt = 1007825738
Expected: True
Actual: False
at
但是,如果您使用 dotnet test
将会成功,因为“数据生成”和测试运行将在一个进程上启动
关于c# - 来自 xunit MemberData 函数的静态数据被计算两次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53071355/
memberData
有什么区别
{@code memberData} 和有什么区别?和 memberData在 JavaDoc 中 最佳答案 有两个主要区别: {@code ...}更简洁:更易于阅读(和输入)。 {@code ..
当您将 [Theory] 与 [InlineData] 一起使用时,它将为提供的每项内联数据创建一个测试。但是,如果您使用 [MemberData],它只会显示为一个测试。 有没有办法让 [Membe
我在计算两次 C# Xunit 测试中来自静态类的计算数据时遇到了一些问题。 这将用于的实际生产代码要复杂得多,但后面的代码足以展示我所看到的问题。 在下面的代码中,我有一个随机生成的、延迟加载的 i
我正在编写一个 xunit 测试来测试根据空格分割句子的实用方法的功能。例如:输入:“谁去那里?”,输出:{“Who”,“goes”,“there”}字符串的集合/列表。 我尝试过以下操作 [
假设我有以下使用 xUnit 编写的测试用例: public static IEnumerable testValues = new List { new object[] {new doub
使用 xUnit.net,Theory 是否有可能使其 MemberData 源自派生类? public abstract class BaseTest { public abstract I
我正在尝试使用 xunit 的 MemberDataAttribute 返回键/值列表。 例如,像这样: [Theory] [MemberData("ValidCardData")] public v
我是一名优秀的程序员,十分优秀!