В xUnit/Shouldly/AutoMoq/Autofixture мы можем передать тип, используя InlineAutoMoqData, который можно использовать как <T> в самом тесте?
У меня есть проблема в модульном тестировании, которую я не смог решить. Я думаю, что самый краткий способ сказать это:
Я хочу иметь возможность использовать Тип, предоставленный в параметрах Теории InlineAutoMoqData, как T в методе Должно Должно. Это позволило бы мне создавать различные тесты строк (я полагаю, что в этой структуре это встроенные теории), ожидающие различные типы исключений, если с методом связано несколько объектов.
Я не уверен, возможно ли это, но вот пример самого модульного теста.
[Theory]
[InlineAutoMoqData("bork", typeof(FileTypeNotRecognizedException))]
public void Build_ReturnsSpecificException_FileNamePassedIn(string fileName, Type expected, ProcessFactory sut)
{
Should.Throw<expected>(() => sut.Build(fileName));
}
Перед тем, как озадачиться и опубликовать это, я рассмотрел следующие вопросы: динамически создать универсальный тип для шаблона и создать экземпляр универсального типа
Возможно ли что-то подобное?
Редактировать:
Я вижу, что в xUnit я могу добиться этого с помощью метода Assert.Throws(Type, Delegate).
[Theory]
[InlineAutoMoqData("bork", typeof(FileTypeNotRecognizedException))]
public void Build_ReturnsSpecificException_FileNamePassedIn(string fileName, Type expected, ProcessFactory sut)
{
Assert.Throws(expected, () => sut.Build(fileName));
}
Я все еще хотел бы знать, есть ли способ достигнуть этого всякий раз, когда я хочу, чтобы Тип был в Обобщенном Методе.
1 ответ
Вы не можете, кроме использования Reflection, похожи на две ссылки, которые вы упомянули.
Тем не менее, вы можете сделать маленький трюк, чтобы добиться того, что вы хотите. Это уродливо и непрактично, и я не рекомендую использовать его, но просто для удовольствия...
Создайте универсальный класс, содержащий ваш параметризованный тест:
public class Test<T> where T : Exception
{
public virtual void Build_ReturnsSpecificException_FileNamePassedIn(
string fileName,
ProcessFactory sut)
{
Assert.Throws<T>(() => sut.Build(fileName));
}
}
Для каждого параметра (тип исключения) вы создаете класс, унаследованный от общего, переопределяете метод теста и используете InlineAutoMoqData
:
public class TestFileNotFound : Test<FileTypeNotRecognizedException>
{
[Theory]
[InlineAutoMoqData("bork")]
public override void Build_ReturnsSpecificException_FileNamePassedIn(string fileName,
ProcessFactory sut)
{
base.Build_ReturnsSpecificException_FileNamePassedIn(fileName, sut);
}
}
public class TestAnotherException : Test<Exception>
{
[Theory]
[InlineAutoMoqData("borg")]
public override void Build_ReturnsSpecificException_FileNamePassedIn(string fileName,
ProcessFactory sut)
{
base.Build_ReturnsSpecificException_FileNamePassedIn(fileName, sut);
}
}
Конечно, вы можете сделать то же самое, используя универсальный метод вместо универсального класса, но это тоже выглядит глупо:
public void Build_ReturnsSpecificException_FileNamePassedIn<TException>(string fileName,
ProcessFactory sut)
where TException : Exception
{
Assert.Throws<TException>(() => sut.Build(fileName));
}
[Theory]
[InlineAutoMoqData("bork")]
public void Build_ReturnsSpecificException_FileNamePassedIn(string fileName,
ProcessFactory sut)
{
Build_ReturnsSpecificException_FileNamePassedIn<FileTypeNotRecognizedException>(fileName, sut);
}
[Theory]
[InlineAutoMoqData("borg")]
public void Build_ReturnsAnotherException_FileNamePassedIn(string fileName,
ProcessFactory sut)
{
Build_ReturnsSpecificException_FileNamePassedIn<Exception>(fileName, sut);
}
Как вы обнаружили, xUnit.net имеет неуниверсальный Assert.Throws
это занимает Type
и вы должны использовать это вместо этого взломать.