SpockMockStatic方法

SpockMockStatic方法

参考: https://blog.csdn.net/knighttools/article/details/44630975

static方法

import com.meituan.mafka.client.producer.IProducerProcessor;
import com.meituan.mdp.langmodel.api.message.AssistantMessage;
import com.sankuai.gaigc.arrange.common.core.promptflow.entity.aigc.flow.cost.collect.AigcFlowCostCollect;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Optional;

/**
 * 计算费用flow调用model产生的资费实体
 */
@Slf4j
public class SendCalculateFlowCostMQMessage {

    private IProducerProcessor aigcFlowCostCollectRecordProducer;

    public SendCalculateFlowCostMQMessage(IProducerProcessor aigcFlowCostCollectRecordProducer) {
        this.aigcFlowCostCollectRecordProducer = aigcFlowCostCollectRecordProducer;
    }
    //mock 这个静态方法.
    public static SendCalculateFlowCostMQMessage create(IProducerProcessor aigcFlowCostCollectRecordProducer) {
        return new SendCalculateFlowCostMQMessage(aigcFlowCostCollectRecordProducer);

    }

    /**
     * 发送计算费用的MQ消息。
  
     */
    public void send(String flowId, String appId, String modelName, AssistantMessage assistantMessage) {
       	//...  
     	//内部方法....
                    AigcFlowCostCollect aigcFlowCostCollect = AigcFlowCostCollect
                            .create(xxx,xxx,xxx  );
                    aigcFlowCostCollect.sendMsg(aigcFlowCostCollectRecordProducer);
 	  //...
   
}

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.dianping.cat.Cat;
import com.meituan.mafka.client.producer.IProducerProcessor;
import com.meituan.mafka.client.producer.ProducerResult;
import com.meituan.mafka.client.producer.ProducerStatus;
import com.sankuai.gaigc.arrange.common.util.RetryUtils;
import com.sankuai.gaigc.arrange.dao.dal.entity.AigcFlowCostCollectRecordDO;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import java.util.Objects;

/**
 * flow计费实体
 */
@Slf4j
public class AigcFlowCostCollect {

    public ProducerResult sendMsg(IProducerProcessor producerProcessor) {
        // 重试3次
        return RetryUtils.withRetry(() -> doSendMsg(producerProcessor), 3);
    }

    private ProducerResult doSendMsg(IProducerProcessor producerProcessor) {
        try {
            String jsonString = JSONObject.toJSONString(this);
			// mock 这儿的方法...
            ProducerResult producerResult = producerProcessor.sendMessage(jsonString);
      
            return producerResult;
        } catch (Exception e) {
         
            throw new RuntimeException("记录flow费用异常");
        }
    }
}

spock-PowerMockito

注意事项.

测试类上打 @RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(Sputnik.class) 这两个注解

然后测试类上打@PrepareForTest(SendCalculateFlowCostMQMessage.class) , 其中SendCalculateFlowCostMQMessage就是你要mock的静态方法所在的类


import org.assertj.core.util.Lists
import org.junit.runner.RunWith
import org.mockito.Mockito
import org.powermock.api.mockito.PowerMockito
import org.powermock.core.classloader.annotations.PowerMockIgnore
import org.powermock.core.classloader.annotations.PrepareForTest
import org.powermock.modules.junit4.PowerMockRunner
import org.powermock.modules.junit4.PowerMockRunnerDelegate
import org.spockframework.runtime.Sputnik
import spock.lang.Specification
import spock.lang.Unroll

@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(Sputnik.class)
@PrepareForTest(SendCalculateFlowCostMQMessage.class)
@PowerMockIgnore("javax.net.ssl.*")
class FunctionCallingSpec extends Specification {

    FunctionCalling functionCalling
    IProducerProcessor aigcFlowCostCollectRecordProducerMock = Mock(IProducerProcessor)

    def setup() {
        functionCalling = new FunctionCalling()
        functionCalling.aigcFlowCostCollectRecordProducer = aigcFlowCostCollectRecordProducerMock
    }

    /**
     *对SendCalculateFlowCostMQMessage.create静态方法进行mock
     * 
     */
    @Unroll
    def "test execute with flow"() {
        given:
        PowerMockito.mockStatic(SendCalculateFlowCostMQMessage.class)
        SendCalculateFlowCostMQMessage create = SendCalculateFlowCostMQMessage.create(aigcFlowCostCollectRecordProducerMock)
        PowerMockito.when(SendCalculateFlowCostMQMessage.create(Mockito.any(IProducerProcessor.class)))
                .thenReturn(create);
        //mock方法
        aigcFlowCostCollectRecordProducerMock.sendMessage(_) >> new ProducerResult(ProducerStatus.SEND_OK)
        when:
        Map<String, Object> result = functionCalling.execute()

        then:
        result.size() > 0
    }

}

可以发现mock成功了.

image

原理

PowerMock简单实现原理

  • 当某个测试方法被注解@PrepareForTest标注以后,在运行测试用例时,会创建一个新的org.powermock.core.classloader.MockClassLoader实例,然后加载该测试用例使用到的类(系统类除外)

  • PowerMock会根据你的mock要求,去修改写在注解@PrepareForTest里的class文件(当前测试类会自动加入注解中),以满足特殊的mock需求。例如:去除final方法的final标识,在静态方法的最前面加入自己的虚拟实现等。

  • 如果需要mock的是系统类的final方法和静态方法,PowerMock不会直接修改系统类的class文件,而是修改调用系统类的class文件,以满足mock需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值