自学内容网 自学内容网

Spock使用Spy来Mock内部调用的方法

使用Spy来Mock内部调用的方法

如果使用Spy不生效参考

使用前先看看哪些场景不生效,避免浪费太多时间,我曾经就是mock一个方法折腾两个小时都没弄出来,后来问了 小美智能助理 ,告诉我其中private修饰的方法不生效..我把private改成protected​ 修饰之后, 再次重启单测,立马就好使了.

https://blog.csdn.net/qq_41489540/article/details/139861513

示例

在Spock框架中,要mock一个类中调用的另一个方法,通常需要使用Spock的Spy功能。Spy允许你在一个实例上部分地mock方法,这意味着你可以选择性地mock某些方法,而其他方法则保持原有行为。以下是如何使用Spy来mock内部方法调用的步骤:

示例代码

假设你有一个Calculator​类,它有一个calculate​方法,这个方法内部调用了add​方法。你想要mock掉add​方法。

class Calculator {
    int calculate(int a, int b) {
        return add(a, b)
    }
// 内部调用的方法
    private int add(int a, int b) {
        return a + b
    }
}

class CalculatorSpec extends Specification {
    def "should mock internal add method"() {
        given:
        def calculator = Spy(Calculator)

        when:
// 正常调用calculate方法
        calculator.calculate(2, 3) 

        then:
        // mock掉add方法,当它被调用时返回10
        1 * calculator.add(2, 3) >> 10 
// 验证calculate方法的结果被mock方法影响
        calculator.calculate(2, 3) == 10 
    }
}

在这个例子中,我们首先创建了Calculator​类的一个Spy对象。然后,我们使用1 * calculator.add(2, 3) >> 10​这行代码来指定当add​方法被调用时,它应该返回10而不是执行实际的加法操作。最后,我们验证calculate​方法的结果是否如我们所模拟的那样返回了10。

注意事项
  • 请注意,Spy通常用来mock非静态的实例方法。如果需要mock静态方法或构造函数,你可能需要其他技术或工具,如PowerMock。
  • 当使用Spy时,确保只mock你需要改变行为的方法。如果你不小心mock了不应该mock的方法,可能会导致测试结果不可靠。
  • 在使用Spy时,原始的方法逻辑不会被执行,除非你使用GroovySpy​并指定callable​返回真实的方法调用。
  • 在实际的测试场景中,如果一个方法的内部实现对于你的测试用例不是很重要,使用Spy可以帮助你集中精力在你关心的行为上。

使用Spock的Spy功能可以使你在测试过程中有效地控制类的内部行为,这对于只想测试类的一部分行为而不是整个类的行为时非常有用。

如果你想mock的内部调用的方法是void怎么办?

被mock的代码片段

    public Map<String, Object> runFlow (Flow flow) {
        try {
            DagEngine<Map<String, Object>> engine = buildEngine(flow);
            //假如说我想mock下面这个.这个是内部调用的方法,它是被上面实例化的engine去调用的.
            engine.runAndWait(flow);
            //......业务代码逻辑 
            return  xxxxxxxxxxxx;
        } catch (Exception e){
          //xxxxx

        } finally {
          //xxxxx
        }
    }

mock代码示例


    def "runFlow"() {
        given:
        DagEngine<Map<String, Object>> engineOriginal = new FlowEngineBuilder<Map<String, Object>>()
                .setFlow(flow)
                .setInputParams(inputParams)
                .setEnvMap(envMap)
                .setRunMode(runMode)
                .setExecutor(Executors.newSingleThreadExecutor())
                .build();
        PromptFlowEngine promptFlowEngine = Spy(PromptFlowEngine.class)

        DagEngine<Map<String, Object>> engine = Spy(engineOriginal)
        promptFlowEngine.buildEngine(flow, inputParams, envMap, runMode) >> engine

        engine.runAndWait(_) >> {}
        when:
        def flowResult = promptFlowEngine.runFlow(flow, inputParams, envMap, runMode)
        then:
        flowResult != null
    }

promptFlowEngine.runFlow方法会调用到 engine.runAndWait ,我想mock engine.runAndWait, 但是它是void修饰的, 解决办法很简单,

就是先mock buildEngine()方法,让它返回 "DagEngine<Map<String, Object>> engine = Spy(engineOriginal)" 这个被Spy好的engine对象, 然后再 mock"engine.runAndWait(_) >> {}" ,注意,>>后面的 {} ,这个"{}" 里面留空,就代表是void返回值.


原文地址:https://blog.csdn.net/qq_41489540/article/details/139861463

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!