Я испытываю затруднения из-за некоторых модульных тестов MSTest, которые передают, когда я выполняю их индивидуально, но сбой, когда я выполняю весь класс модульного теста. Тесты тестируют некоторый код, с которым SLaks помог мне ранее, и он предупредил меня, что я делал, не было ориентировано на многопотоковое исполнение. Однако теперь мой код более сложен, и я не знаю, как пойти о создании его ориентированный на многопотоковое исполнение. Вот то, что я имею:
public static class DLLConfig
{
private static string _domain;
public static string Domain
{
get
{
return _domain = AlwaysReadFromFile
? readCredentialFromFile(DOMAIN_TAG)
: _domain ?? readCredentialFromFile(DOMAIN_TAG);
}
}
}
И мой тест прост:
string expected = "the value I know exists in the file";
string actual = DLLConfig.Domain;
Assert.AreEqual(expected, actual);
Когда я запускаю этот тест отдельно, он передает. Когда я выполняю его вместе со всеми другими тестами в тестовом классе (которые выполняют подобные проверки на различных свойствах), actual
null
и тестовые сбои. Я отмечаю, что это не проблема со свойством, тип которого является пользовательским Enum
введите; возможно, у меня есть эта проблема с Domain
свойство, потому что это - a string
? Или возможно это - многопоточная проблема с тем, как MSTest работает?
Я подозреваю, что другие тесты изменяют какое-то значение в классе DLLConfig
, что приводит к изменению результата геттера. Юнит-тесты всегда должны запускаться из известного начального состояния, поэтому вы должны либо установить это в самом методе теста, либо в методе, помеченном атрибутом TestInitialize
, который запускается перед каждым тестом.
Ваш тест зависит от внешнего файла. Вместо вызова функции, которая напрямую обращается к файлу, вы должны заставить DLLConfig.Domain вызывать метод в другом классе.
public static string Domain
{
get
{
return _domain = AlwaysReadFromFile
? CredentialReader.Read(DOMAIN_TAG)
: _domain ?? CredentialReader.Read(DOMAIN_TAG);
}
}
Затем вы можете инициализировать DllConfig с помощью mock / fake / stub CredentialReader, где вы можете контролировать его возвращаемое значение. Помните, что вы проверяете, что DLLConfig.Domain возвращает правильное значение на основе условия AlwaysReadFromFile
. Вы не должны одновременно проверять, откуда исходит это значение (или существует ли оно вообще).
Повышение «тестируемости» класса DLLConfig дает дополнительное преимущество в виде разделения проблем. Когда вы думаете о классе и не можете не сказать: «Этот класс выполняет это И , что » (абстрагирование данных конфигурации и чтение этих данных из файла), это хорошая ставка. класс смешивает заботы и пытается сделать слишком много. Если DLLConfig является абстракцией данных конфигурации, он должен сосредоточиться только на этом и оставить место происхождения данных другому классу.