模拟Logger时的问题

时间:2014-01-30 14:20:27

标签: unit-testing grails groovy mocking spock

在模拟类的日志字段时,我遇到了一个奇怪的问题。两次运行相同的测试会第二次显示错误。这是代码示例:

class AccountConfigJSON {
    static Logger log = Logger.getLogger(AccountConfigJSON.class)

    def AccountConfigJSON(String jsonString) {
        if (jsonString) {
            json = new JSONObject(jsonString)
        } else {
            log.debug("No JSON string for account config. Will not parse")
        }
    }
}

这是规范

class AccountConfigJSONUnitSpec extends UnitSpec {

    def loggerMock

    def setup(){
        loggerMock = Mock(org.apache.log4j.Logger)
        org.apache.log4j.Logger.metaClass.static.getLogger = { Class clazz -> loggerMock }
    }

    def 'If jsonString is null, a log is written'(){
        when:
            new AccountConfigJSON("")
        then:
            1 * loggerMock.debug("No JSON string for account config. Will not parse")
    }

    def 'If jsonString is empty, a log is written'(){
        when:
            new AccountConfigJSON("")
        then:
            1 * loggerMock.debug("No JSON string for account config. Will not parse")
    }
}

第二次测试失败显示

|  Too few invocations for:

1 * loggerMock.debug("No JSON string for account config. Will not parse")   (0 invocations)

但使用Idea调试应用程序,显然它运行这句话。有什么想法吗?

1 个答案:

答案 0 :(得分:4)

看起来很奇怪,实际的呼叫被执行但是没有记录的交互。你可以通过明确地将模拟的记录器分配给类来解决它:

def setup(){
    loggerMock = Mock(org.apache.log4j.Logger) 
    AccountConfigJSON.log = loggerMock
}

从“互动”的定义来看,我认为上述设置是最佳方式。

  

交互只是一种常规的方法调用吗?

     

不完全。虽然交互看起来类似于常规方法   调用,它只是一种表达方法调用的方式   预计会发生。考虑互动的好方法是:   正则表达式,模拟对象上的所有传入调用都是   与...相匹配。根据具体情况,可以进行互动   匹配零个,一个或多个调用。

仅在处理类中的static对象属性时才会发生这种情况。时刻记录器在被测试的类中被定义为非静态的,一切都按预期工作,无需解决。