我想为一组不同的异常类型编写一个单元测试。我的常用方法是对一组特定的测试输入使用 InlineAutoMoqData。这对于值来说效果很好,但我无法让它对于类型起作用。
您可以在下面找到我的想法/希望的解决方案:
[Theory]
[InlineAutoMockData(typeOf(HttpRequestException)]
[InlineAutoMockData(typeOf(InvalidOperationException)]
public async void MyTestFunction_Should_HandleExceptions(Type exceptionType, Mock<HttpClient> clientMock)
{
// Arrange
var cut = CreateCut();
clientMock.Setup(c => c.SendAsync()).ThrowsAsync(new Exception()); // here I want to create a generic Exception dependend on the exceptionType instead of "new Exception"
// Act
var result = cut.DoSomething();
// Assert
result.Should().BeTrue();
}
我可以添加一个 switch case 检查“exceptionType”并最小起订量客户端依赖它。这个解决方案有效,但感觉不“正确”。我认为必须有一个更优雅的解决方案。
最佳答案
xUnit 支持通用参数。 所以你应该能够做这样的事情。
[Theory]
[MemberData(nameof(Exceptions))]
#pragma warning disable xUnit1026 // Theory methods should use all of their parameters
public async Task MyTestFunction_Should_HandleExceptions<TException>(TException _, Mock<HttpClient> clientMock)
#pragma warning restore xUnit1026 // Theory methods should use all of their parameters
where TException : Exception, new()
{
// Arrange
var cut = CreateCut();
clientMock.Setup(c => c.SendAsync()).Throws<TException>();
// Act
var result = cut.DoSomething();
// Assert
result.Should().BeTrue();
}
public static TheoryData<Exception> Exceptions() => new()
{
new HttpRequestException(),
new InvalidOperationException()
};
由于我无法运行您的代码片段,因此这是我用来验证上述想法是否有效的代码。
[Theory]
[MemberData(nameof(Exceptions))]
#pragma warning disable xUnit1026 // Theory methods should use all of their parameters
public async Task MyTestFunction_Should_HandleExceptions<TException>(TException _)
#pragma warning restore xUnit1026 // Theory methods should use all of their parameters
where TException : Exception, new()
{
// Arrange
var handlerMock = new Mock<HttpMessageHandler>();
handlerMock
.Protected()
.Setup<Task<HttpResponseMessage>>(
"SendAsync",
ItExpr.IsAny<HttpRequestMessage>(),
ItExpr.IsAny<CancellationToken>()
)
.Throws<TException>();
var client = new HttpClient(handlerMock.Object)
{
BaseAddress = new Uri("http://test.com/")
};
var cut = new Cut(client);
// Act
var result = await cut.DoSomething();
// Assert
result.Should().BeTrue();
}
public static TheoryData<Exception> Exceptions() => new()
{
new HttpRequestException(),
new InvalidOperationException()
};
private class Cut
{
private readonly HttpClient httpClient;
public Cut(HttpClient httpClient)
{
this.httpClient = httpClient;
}
public async Task<bool> DoSomething()
{
var result = await httpClient.SendAsync(new HttpRequestMessage());
return result.IsSuccessStatusCode;
}
}
关于c# - 如何模拟 "Throws"和 "ThrowsAsync"中的异常类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75947002/