Java 模拟单例的getInstance()以返回子类(Quarkus)

Java 模拟单例的getInstance()以返回子类(Quarkus),java,unit-testing,mockito,singleton,quarkus,Java,Unit Testing,Mockito,Singleton,Quarkus,我试图模拟下面一个单例类的getInstance(),以返回模拟的类: 基类(passo9()是要模拟的方法): 包br.com.bb.ids.robo.passo09; 导入br.com.bb.ids.robo.passo09.dao.RoboSkipDao; 导入br.com.bb.ids.robo.passo09.exceptions.RoboSkipDaoFindException; 导入br.com.bb.ids.robo.passo09.exceptions.RoboSkipDaoM

我试图模拟下面一个单例类的getInstance(),以返回模拟的类:

  • 基类(passo9()是要模拟的方法):
  • 包br.com.bb.ids.robo.passo09;
    导入br.com.bb.ids.robo.passo09.dao.RoboSkipDao;
    导入br.com.bb.ids.robo.passo09.exceptions.RoboSkipDaoFindException;
    导入br.com.bb.ids.robo.passo09.exceptions.RoboSkipDaoMergeException;
    导入br.com.bb.ids.robo.passo09.models.RoboSkip;
    导入javax.enterprise.context.ApplicationScoped;
    @适用范围
    公共级电动机{
    私人静电马达实例;
    公共静态马达getInstance(){
    if(实例==null){
    实例=新电机();
    }
    返回实例;
    }
    私家车(){}
    /**
    *要模拟的方法
    * 
    *@返回错误代码(如果成功,则为0)
    *@Exception抛出任何非预期的异常
    */
    public int passo9()引发异常{
    试一试{
    系统输出打印(Verifica o ponto onde o robôparou);
    RoboSkipDao rsDao=RoboSkipDao.getInstance();
    RoboSkip rs=rsDao.findByPasso(9);
    int resultadoPasso=Integer.parseInt(rs.getValor());
    rs.setValor(Integer.toString(resultadoPasso+32768));
    合并(rs);
    }
    渔获物(Roboskipdaofindexe){
    System.out.println(“Erro ao consultar registro em robo_skip,passo=9”);
    e、 printStackTrace();
    返回2;
    }
    捕获(数字格式){
    System.out.println(“Número do registro inválido em robo_skip,passo 9”);
    e、 printStackTrace();
    返回3;
    }
    捕获(Roboskipdaoe){
    System.out.println(“Erro ao atualizar registro em robo_skip,passo 9”);
    e、 printStackTrace();
    返回8;
    }
    返回0;
    }
    }
    
  • 要调用的扩展类,而不是上面的Motor
  • 包br.com.bb.ids.robo.passo09;
    导入io.quarkus.test.Mock;
    导入javax.enterprise.context.ApplicationScoped;
    @嘲弄
    @适用范围
    公共级摩托车{
    公共摩托摩克(摩托m){}
    @凌驾
    public int passo9()引发异常{
    System.out.println(“passo9()mockado-返回0”);
    返回0;
    }
    }
    
  • Quarkusmain类(Motor.getInstance()应返回MotorMock,而不是在我下面的测试中返回Motor):
  • 包br.com.bb.ids.robo.passo09;
    导入io.quarkus.runtime.quarkus;
    导入io.quarkus.runtime.annotations.QuarkusMain;
    @夸克斯曼
    公共班机{
    公共静态void main(字符串[]args){
    如果(args.length!=1 | |!args[0]。匹配(“true | false”)){
    系统错误println(“Indicação em desenvolvimento(真/假)obrigatória”);
    返回;
    }
    布尔值emDesenvolvimento=boolean.parseBoolean(args[0]);
    System.out.println(“Iniciando aplicação…”);
    试一试{
    Motor=Motor.getInstance();
    电机。setEmDesenvolvimento(emDesenvolvimento);
    int returnCode=motor.passo9();
    System.out.println(“Finalizando aplicação…”);
    Quarkus.asyncExit(返回代码);
    }
    捕获(例外e){
    e、 printStackTrace();
    }        
    }
    }
    
  • 我的测试模块:
  • 包br.com.bb.ids.robo.passo09;
    导入io.quarkus.test.junit.QuarkusMock;
    导入io.quarkus.test.junit.QuarkusTest;
    导入javax.inject.inject;
    导入org.junit.jupiter.api.Test;
    @夸克斯特
    公共类测试{
    @注入
    电机;
    @试验
    公共void testMain(){
    MotorMock mm=新的MotorMock(Motor.getInstance());
    Mockito.when((Motor)mm.getInstance()),然后返回(mm);
    QuarkusMock.installMockForType(mm,电机类);
    System.out.println(“Testando Main.Main(args)…”;
    字符串[]args=新字符串[1];
    args[0]=“真”;
    Main.Main(args);
    System.out.println(“Testes com Main.Main(args)efetuados com successo”);
    }   
    }
    

    我想在测试用例中调用MotorMock.passo9(),而不是Motor.passo9()。我如何做到这一点?如果可能,请与代码示例共享。

    您不应使用
    @Mock
    @ApplicationScoped
    注释
    MotorMock
    。您可以删除它们并重试吗?首先,去掉
    getInstance()
    方法。永远不要以编程方式实例化应该由CDI容器管理的类。相反,可以使用
    @Inject
    ,或者如果确实需要,可以使用
    CDI.current()
    。然后,
    QuarkusMock.installMockForType
    应该可以工作。@Ladicek我真的必须在这个类上使用
    getInstance()
    (无法摆脱它)。如果可能的话,我希望看到
    CDI.current()
    的编码示例以及
    QuarkusMock.installMockForType
    。我100%确信可以摆脱手动实例化该类。最坏的情况是
    getInstance
    方法如下:
    返回CDI.current().select(Motor.class).get()
    。然而,在绝大多数情况下,您可以摆脱这种情况,使用
    @Inject
    、producer方法等。要点是:您将类声明为bean(
    @ApplicationScoped
    ),因此您应该让CDI容器管理其生命周期(这也是模拟可以实际工作的原因),并且永远不要手动实例化它。