【问题标题】:How to unit test logging error with Spock framework in groovy如何在 groovy 中使用 Spock 框架对日志记录错误进行单元测试
【发布时间】:2014-08-17 19:34:38
【问题描述】:

所以我有一个类,它有一个记录消息的方法:

class Car {
    private Logger logger = LoggerFactory.getLogger(Car.class);


    void startCar() {
        logger.error("car stopped working");
    }
}

如何使用 spock 测试框架测试是否记录了错误?

class CarTest extends Specification {
    def "test startCar"() {
        given:
        Car newCar = new Car();

        when:
        newCar.startCar();

        then:
        // HOW CAN I ASSERT THAT THE MESSAGE WAS LOGGED???
    }
}

【问题讨论】:

    标签: unit-testing logging groovy spock


    【解决方案1】:

    您可以检查记录器上的错误调用

    @Grab(group='org.spockframework', module='spock-core', version='0.7-groovy-2.0')
    @Grab(group='org.slf4j', module='slf4j-api', version='1.7.7')
    @Grab(group='ch.qos.logback', module='logback-classic', version='1.1.2')
    
    import org.slf4j.Logger
    
    class MockLog extends spock.lang.Specification {
    
        public class Car {
            private Logger logger = org.slf4j.LoggerFactory.getLogger(Car.class);
            void startCar() {
                logger.error('car stopped working');
            }
        }
    
        def "mock log"() {
        given:
            def car = new Car()
            car.logger = Mock(Logger)
        when:
            car.startCar()
        then:
            1 * car.logger.error('car stopped working')
        }
    }
    

    编辑:完整示例https://github.com/christoph-frick/spock-test-logging

    【讨论】:

    • groovy.lang.ReadOnlyPropertyException: Cannot set readonly property: LOG 。在您的示例中,您可以访问 car.logger - 但是如果该类不在 Spock Testclass 中,如何访问?
    • 这个例子似乎具有误导性。在现实生活中,您的记录器无法访问您的测试代码(Car 类不在规范中)
    • @mattfreake 我添加了一个指向完整示例的链接以显示,这不依赖于测试中的类。这样做是为了有一个简短的例子。如果你的意思是别的,请详细说明。如果您反对编写这样的测试,那么我支持您 - 但请归咎于 OP 而不是答案。如果您需要的东西记录得非常糟糕,值得编写一个测试,那么为它提供一个适当的基础设施。如果测试多毛或难以编写,则不是测试错误,而是 SUT 的错误。
    • 您的汽车实例如何访问记录器?不是私人的吗?
    • @L.Dai Groovy 和/或 Spock 不在乎。 jvm 上的私有也不是真正私有的(至少可以通过反射访问)
    【解决方案2】:

    我的 Loggers 是私有静态 final 所以我不能使用上面提到的解决方案,而不是使用反射。

    如果您使用的是 Spring,则可以访问 OutputCaptureRule。

    @Rule
    OutputCaptureRule outputCaptureRule = new OutputCaptureRule()
    
    def test(){
    outputCaptureRule.getAll().contains("<your test output>")
    }
    

    【讨论】:

    • 这不仅适用于 Spring,也适用于 Travis CI。以前,OutputCapture 是我将在 Spring/Spock 中使用的类,但它已被弃用,并且会导致 CI​​ 构建失败。我很高兴我搜索了另一个答案并找到了这个!另外,我觉得我应该提到我们正在使用@Slf4j,这是完美的。谢谢!
    • 您可能还需要添加依赖'org.spockframework:spock-junit4:2.0-groovy-3.0' 并在log4j2 配置文件中为您的Console appender 设置参数follow="true"(参见stackoverflow.com/a/70350184/10592946
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-27
    • 1970-01-01
    相关资源
    最近更新 更多