3年前 (2021-06-27)  Spock系列 |   抢沙发  2550 
文章评分 1 次,平均分 4.0

之前的Spock系列mock静态方法主要是通过使用PowerMock实现的,但是使用JMock的同学也挺多的,所以这篇文章讲下在Spock中如何使用JMockit来mock静态方法。

比如下面的业务代码demo,记录日志的logger对象是调用LoggerServiceFactory工厂类的静态方法获取的,这时候就可以使用JMockit把他的静态方法getLoggerService给mock掉,因为日志类一般初始化的时候会加载一些配置资源,跑单测的时候比较耗时间。

实例代码如下:

public class MyClass {
 
    private LoggerService logger = LoggerServiceFactory.getLoggerService();
 
    public int testStatic(int orderId) {
        logger.info("testStatic request", orderId);
 
        if (ConfigUtils.staticMethod()) {
            // 业务逻辑...
            return 1;
        } else {
            // 业务逻辑...
            return 2;
        }
    }
}

单元测试代码:

class SpockWithJMockTest extends Specification {
   def instance = new MyClass()
   def logger = Mock(LoggerService)
 
    void setupSpec() {
        new MockUp<LoggerServiceFactory>() {
            @Mock
            static LoggerService getLoggerService() {
                return null
            }
        }
    }
 
    void setup() {
        instance.logger = logger
    }
}

用法和在Junit里使用JMock一样,没什么区别。

主要是如果你想结合Spock的where表格方式实现jmock多次mock(动态mock)的话需要结合groovy闭包的用法,闭包的用法参考之前一篇文章:Spock单元测试高级语法-Groovy闭包

比如还是上面这个MyClass业务类的testStatic方法内部会调用一个工具类的静态方法ConfigUtils.staticMethod(),然后根据他的返回值走不同的逻辑,

可以使用jmock+where每次mock不同的值返回,以覆盖不同的分支逻辑,完整代码如下:

import mockit.Mock
import mockit.MockUp
import mockit.internal.state.SavePoint
import spock.lang.Specification
import spock.lang.Unroll
 
/**
 *
 * @Author: java老k
 * @Date: Created in 2021/5/28 11:07
 * @Modified By:
 */
class SpockWithJMockTest extends Specification {
 
    def instance = new MyClass()
    def logger = Mock(LoggerService)
 
    void setupSpec() {
        new MockUp<LoggerServiceFactory>() {
            @Mock
            static LoggerService getLoggerService() {
                return null
            }
        }
    }
 
    void setup() {
        instance.logger = logger
    }
 
    def savePoint = new SavePoint()
 
    def cleanup() {
        savePoint.rollback() // 如果是多次使用jmock,需要每次执行完一次用例后清除下保存点,否则上一次的jmock值会影响后续的jmock
    }
 
    @Unroll
    def "测试JMock静态方法"() {
        given:
        mockClosure()
 
        when:
        def response = instance.testStatic(1)
 
        then:
        response == result
 
        where: "使用JMock动态mock"
        mockClosure       | result
        mockStatic(true)  | 1
        mockStatic(false) | 2
    }
 
    def mockStatic(bool) {
        // 这里返回的是闭包
        return {new MockUp<ConfigUtils>() {
            @Mock
            boolean staticMethod(){
                return bool
            }
        }}
    }
}

注:普通的实例方法建议还是使用Spock自带的mock来模拟(比如使用Spring @Autowired注入的实例,理论上都可以使用Spock自带的mock)

 

除特别注明外,本站所有文章均为老K的Java博客原创,转载请注明出处来自https://javakk.com/2062.html

关于

发表评论

表情 格式

暂无评论

登录

忘记密码 ?

切换登录

注册