У меня возникли проблемы с вычислением данных из статического класса в тесте 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}");
}
}