#c# #moq #xunit
Вопрос:
Приведен следующий пример помощника
public static class RuntimeHelper
{
public static bool IsLinux => RuntimeInformation.IsOSPlatform(OSPlatform.Linux);
public static bool IsMac => RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
public static bool IsWindows => RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
}
Есть несколько вопросов
- Должен ли я вообще проводить модульное тестирование таких полей? (это может быть основано на мнении)
- Есть ли способ создавать модульные тесты на основе операционной системы?
Примером реализации может быть
public sealed class RuntimeHelperTests
{
// IF RUNNING ON WINDOWS
[Fact]
public void TheOSShouldBeWindows()
{
Assert.True(RuntimeHelper.IsWindows);
}
[Fact]
public void TheOSShouldNotBeLinux()
{
Assert.False(RuntimeHelper.IsLinux);
}
[Fact]
public void TheOSShouldNotBeMac()
{
Assert.False(RuntimeHelper.IsMac);
}
// DO THIS FOR THE OTHER OPERATING SYSTEMS TOO
}
Но эти тесты проходят только при запуске на компьютере с Windows…
Комментарии:
1. Трудно ответить на этот вопрос без конкретики того, что
RuntimeInformation
есть. Но в конечном счете вы должны высмеивать любые внешние зависимости. Так что все, что говорит вам «это окна» и т. Д., Должно быть высмеяно2. Кроме того, статика-это нет-нет с точки зрения модульного тестирования. Это делает чрезвычайно трудным любое издевательство. По существу избегайте использования статики, когда это возможно
3. @Liam: RuntimeInformation -это статический класс, предоставляемый .NET
Ответ №1:
Мы можем написать много слоев в нашей логике. На этот счет нет практического верхнего предела. Однако, независимо от того, сколько слоев мы пишем, снаружи всегда есть один слой, который должен взаимодействовать с реальным миром (например, монитор, сеть, операционная система, файловая система, устройство ввода-вывода,…)
Природа зверя такова, что последний слой никогда не может быть по-настоящему протестирован, потому что его зависимости являются внешними ресурсами. Все остальные слои (т. е. не последний) могут быть протестированы, потому что их соседний слой может быть высмеян.
В вашем случае RuntimeInformation
это ваша не поддающаяся блокировке зависимость от реального мира. Это одна из главных проблем static
при тестировании.
Вообще говоря, совет состоит в том, чтобы затем отделить бизнес-логику от внешней зависимости, чтобы вы могли протестировать бизнес-логику, обернув внешнюю зависимость в приятный насмешливый собственный слой. Вот мой ответ, уточняющий именно это.
Однако в вашем случае нет реальной бизнес-логики. Ваш RuntimeHelper
уже является этой абстрактной оболочкой.
Для этого не имеет смысла писать тесты RuntimeHelper
.
Если бы вы создали RuntimeHelper
экземпляр, а не статический, что я настоятельно рекомендую, то вы смогли бы модульно протестировать классы, от которых зависят RuntimeHelper
, путем введения издевки RuntimeHelper
, которая может притворяться, что вы находитесь в какой-либо конкретной ОС, даже если это не так.
Как выполнять определенные модульные тесты только при запуске в определенной операционной системе?
Ты задаешь неправильный вопрос. Вместо того, чтобы писать разные тесты для работы на фактически разных ОС, вы должны писать одни и те же (поведенческие) тесты, но в каждом тесте насмешливо RuntimeHelper
заявлять, что вы работаете в другой ОС.
Например:
[Fact]
public void FilePathService_returns_correct_linux_path()
{
var mockedRuntimeHelper = new MockedRuntimeHelper(OS.Linux);
var filePathService = new FilePathService(mockedRuntimeHelper);
var result = filePathService.GetConfigurationFolder();
result.Should().Be("/path/to/config");
}
[Fact]
public void FilePathService_returns_correct_windows_path()
{
var mockedRuntimeHelper = new MockedRuntimeHelper(OS.Windows);
var filePathService = new FilePathService(mockedRuntimeHelper);
var result = filePathService.GetConfigurationFolder();
result.Should().Be(@"C:pathtoconfig");
}
[Fact]
public void FilePathService_returns_correct_mac_path()
{
var mockedRuntimeHelper = new MockedRuntimeHelper(OS.Mac);
var filePathService = new FilePathService(mockedRuntimeHelper);
var result = filePathService.GetConfigurationFolder();
result.Should().Be(@"whatever a Mac path is, I don't know");
}
Это позволяет протестировать все три поведения, выполняемые в любой операционной системе.
По-прежнему неплохо протестировать свой код на всех ОС, просто чтобы убедиться, что в вашей среде выполнения нет странных крайних случаев, но это не связано с желанием писать конкретные модульные тесты, которые следует запускать только на определенных операционных системах.
Комментарии:
1. Просто короткая заметка. ОП пометил это moq. Поэтому им не нужно на самом деле создавать
MockedRuntimeHelper
. Moq может сделать это за нихvar mockedRuntimeHelper = new Mock<IRuntimeHelper>();
, я бы также посоветовал вам отключить своих иждивенцев с помощью интерфейсов , чтобы облегчить этот процесс