TestCases 如何测试抛出的不同异常?

Posted

技术标签:

【中文标题】TestCases 如何测试抛出的不同异常?【英文标题】:How can TestCases test different exceptions are thrown? 【发布时间】:2021-11-09 16:01:47 【问题描述】:

我是 TestCases 的忠实拥护者,因为它们让测试更多边缘案例变得轻而易举,而且反测试人员似乎对更少的测试代码行更满意。不过,我一直在为异常测试而苦苦挣扎。

在我的代码中,我有一个验证函数,用于检查配置中是否有 1 个且只有 1 个实例。如果有 0 则抛出 KeyNotFoundException,如果超过 1 则抛出 AmbiguousMatchException。

private void ThrowIfNotInConfig(string endpointRef)

    var count = _config.Endpoints?.Count(x => x.Ref.Equals(endpointRef)) ?? 0;
    if (count == 0)
    
        throw new KeyNotFoundException($"nameof(ThrowIfNotInConfig) - " +
                                       $"No Endpoint in appSettings with the ref endpointRef");
    
    if (count > 1)
    
        throw new AmbiguousMatchException($"nameof(ThrowIfNotInConfig) - " +
                                      $"More than 1 Endpoint in appSettings with the ref endpointRef");
    

有没有一种方法可以避免将它们分成 2 个单独的测试,仅仅因为异常类型,这比这更整洁?我不喜欢在测试中尝试捕获,我觉得应该有一种方法来测试异常,就像以前的 ExpectedException 一样。

[TestCase(0, ExpectedResult = "KeyNotFoundException")]
[TestCase(2, ExpectedResult = "AmbiguousMatchException")]
public string ThrowIfNotInConfig_GIVEN_NotASingleEndpointInConfig_THEN_ThrowError(int configOccurrences)

    // Arrange
    const string endpointRef = "ABC";
    var config = _validConfig;
    config.Endpoints.RemoveAll(x => x.Ref == endpointRef);
    config.Endpoints
        .AddRange(Enumerable.Range(0, configOccurrences)
            .Select(x => new MiraklEndpointConfig  Ref = endpointRef )
        );
    _config.Setup(c => c.Value).Returns(config);

    var service = new URLThrottlingService(_mockLogger.Object, _config.Object);
    
    try
    
        // Act
        service.IsOKToCallEndpoint(endpointRef);
    
    catch (Exception exception)
    
        return exception.GetType().Name;
    

    return "";

【问题讨论】:

我可能会让方法接受Type exceptionType,然后在测试方法中使用Assert.Throws(exceptionType, () => ...),并将typeof(KeyNotFoundException) 作为TestCase 属性的参数传入 另见***.com/questions/35061336/… 感谢@canton7,但该链接仅测试是否发生了特定的异常类型。我正在尝试测试当 y 是值时发生的异常类型 x,由测试用例设置 我特指Oliamster's answer 我明白了。我不喜欢测试中的逻辑,但是当你把它去掉时,这确实是一个更简洁的解决方案。我将添加一个答案,以便我可以分享代码 【参考方案1】:

感谢canton7 和Olimasters answer,我现在有了这个,这就是我所追求的

[TestCase(0, typeof(KeyNotFoundException))]
[TestCase(2, typeof(AmbiguousMatchException))]
public void ThrowIfNotInConfig_GIVEN_NotASingleEndpointInConfig_THEN_ThrowError(int configOccurrences, Type exception)

    // Arrange
    const string endpointRef = "ABC";
    var config = _validConfig;
    config.Endpoints.RemoveAll(x => x.Ref == endpointRef);
    config.Endpoints
        .AddRange(Enumerable.Range(0, configOccurrences)
            .Select(x => new MiraklEndpointConfig  Ref = endpointRef )
        );
    _config.Setup(c => c.Value).Returns(config);

    var service = new URLThrottlingService(_mockLogger.Object, _config.Object);

    // Act / Assert
    Assert.Throws(exception, () => service.IsOKToCallEndpoint(endpointRef));

【讨论】:

以上是关于TestCases 如何测试抛出的不同异常?的主要内容,如果未能解决你的问题,请参考以下文章

如何识别抛出的特定异常

使用 sbt 和 testng 时,如何获取测试中抛出的异常的完整堆栈跟踪?

Mockito 如何模拟和断言抛出的异常?

捕获在不同线程中抛出的异常

使用 Assert 测试异常以确保它们被抛出的最佳方法

使用 Assert 测试异常以确保它们被抛出的最佳方法