用于扩展 QuartzJobBean 的类的 Junit

标签 junit

我有一个扩展 QuartzJobBean 的 Java 类,并且已安排在一天中的特定时间。

   public class ServiceJob extends QuartzJobBean {

        @Override
          protected void executeInternal(JobExecutionContext context) {
}

有人可以帮助我了解如何为此创建一个 Junit 测试用例。如何在测试用例中调用 executeInternal() 方法。

感谢您对此的任何帮助。

最佳答案

我为我的工作项目创建了一个解决方案,我同意 adarshdatt 通过导入定义 bean 的配置文件来解决它。您可以在此 blog post 上找到有关它的很好的教程。 ,

为了将来使用,我想展示我如何用 Mocking 解决它,只需使用 Mockito @Mock 注释以这种方式:

SessionConfirmationJob.java

public class SessionConfirmationJob extends QuartzJobBean {
    @Autowired
    private SessionService sessionService;
    @Autowired
    private TransactionService transactionService;
    @Autowired
    private SystemLogger systemLogger;
    public static final String TOKEN = "token";
    private SpringInjectQuartzJobBean springInjectQuartzJobBean;

    public SessionService getSessionService() {
        return sessionService;
    }

    public void setSessionService(SessionService sessionService) {
        this.sessionService = sessionService;
    }

    public TransactionService getTransactionService() {
        return transactionService;
    }

    public void setTransactionService(TransactionService transactionService) {
        this.transactionService = transactionService;
    }

    public void setSpringInjectQuartzJobBean(SpringInjectQuartzJobBean springInjectQuartzJobBean) {
        this.springInjectQuartzJobBean = springInjectQuartzJobBean;
    }

    public SystemLogger getSystemLogger() {
        return systemLogger;
    }

    public void setSystemLogger(SystemLogger systemLogger) {
        this.systemLogger = systemLogger;
    }

    @Override
    protected void executeInternal(JobExecutionContext paramJobExecutionContext) throws JobExecutionException {
        springInjectQuartzJobBean = new SpringInjectQuartzJobBean();
        springInjectQuartzJobBean.injectQuartzJobToSpringApplicationContext(this);
        String token = paramJobExecutionContext.getMergedJobDataMap().getString(TOKEN);
        Session session = sessionService.getByToken(token);
        if (session != null) {
            if (session.getPaymentConfirmation() == null || session.getPaymentConfirmation() != true) {
                Transaction transactionToBeRolledBack = transactionService.getRollBackTransactionOfPayment(session);
                if (transactionToBeRolledBack != null) {
                    try {
                        transactionService.rollBackTransaction(transactionToBeRolledBack);
                    } catch (IOException e) {
                        systemLogger.logException("Exception while rolling back transaction", e);
                    }
                    session = sessionService.getByToken(token);
                    session.setStatus(SessionStatus.FI);
                    session.setPaymentConfirmation(false);
                    sessionService.saveOrUpdate(session);
                }
            }
        }
    }
}

这是我应该编写测试的方法,这是测试类。

SessionConfirmationJobTest.java
@RunWith(MockitoJUnitRunner.class)
public class SessionConfirmationJobTest {
    @Mock
    private SessionService sessionService;
    @Mock
    private TransactionService transactionService;
    @Mock
    private JobExecutionContext ctx;
    @Mock
    private SpringInjectQuartzJobBean springInjectQuartzJobBean;
    private JobDataMap mergedJobDataMap = new JobDataMap();
    @Mock
    private Scheduler scheduler;
    private SessionConfirmationJob sessionConfirmationJob;
    private String token = "payment token";

    @Before
    public void setUp() throws SchedulerException {
        mergedJobDataMap.put(SessionConfirmationJob.TOKEN, token);
        when(ctx.getMergedJobDataMap()).thenReturn(mergedJobDataMap);
        when(ctx.getScheduler()).thenReturn(scheduler);
        when(scheduler.getContext()).thenReturn(null);
        sessionConfirmationJob = new SessionConfirmationJob();
        sessionConfirmationJob.setSessionService(sessionService);
        sessionConfirmationJob.setTransactionService(transactionService);
        sessionConfirmationJob.setSpringInjectQuartzJobBean(springInjectQuartzJobBean);
    }

    /**
     * Test payment confirmation when we have false payment confirmation
     * 
     * @throws JobExecutionException
     */
    @Test
    public void testPaymentRollBackForFalseConfirmation() throws IOException, JobExecutionException {
        Session session = new Session();
        session.setStatus(SessionStatus.AC);
        session.setPaymentConfirmation(false);
        Transaction transaction = new Transaction();
        transaction.setSession(session);
        transaction.setType(TransactionType.SALE);
        transaction.setStatus(TransactionStatus.AP);
        when(sessionService.getByToken(token)).thenReturn(session);
        when(transactionService.getRollBackTransactionOfPayment(session)).thenReturn(transaction);
        when(transactionService.rollBackTransaction(transaction)).thenReturn(true);
        sessionConfirmationJob.execute(ctx);
        Assert.assertEquals(SessionStatus.FI, session.getStatus());
        Assert.assertFalse(session.getPaymentConfirmation());
        verify(sessionService).saveOrUpdate(session);
    }
}

在模拟 Schedular 对象之前,我在 pvs.addPropertyValues(context.getScheduler().getContext()); 处得到 NullPointerException在我模拟 schedular 之后,它解决了,我的测试通过了。下面是
org.springframework.scheduling.quartz.QuartzJobBean#execute(JobExecutionContext context)方法。实际上 executeInternal 是 protected ,所以我们必须先调用 execute 方法,然后调用 executeInternal 方法,该方法在您实现的 Job 类中被覆盖(我的演示是 SessionConfirmationJob)。

QuartzJobBean.java
public abstract class QuartzJobBean implements Job {

    /**
     * This implementation applies the passed-in job data map as bean property
     * values, and delegates to {@code executeInternal} afterwards.
     * @see #executeInternal
     */
    @Override
    public final void execute(JobExecutionContext context) throws JobExecutionException {
        try {
            BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);
            MutablePropertyValues pvs = new MutablePropertyValues();
            pvs.addPropertyValues(context.getScheduler().getContext());
            pvs.addPropertyValues(context.getMergedJobDataMap());
            bw.setPropertyValues(pvs, true);
        }
        catch (SchedulerException ex) {
            throw new JobExecutionException(ex);
        }
        executeInternal(context);
    }

/**
 * Execute the actual job. The job data map will already have been
 * applied as bean property values by execute. The contract is
 * exactly the same as for the standard Quartz execute method.
 * @see #execute
 */
protected abstract void executeInternal(JobExecutionContext context) throws JobExecutionException;

}

如果您有任何问题,请随时通过评论向我提问。

关于用于扩展 QuartzJobBean 的类的 Junit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27552136/

相关文章:

java - 我如何在 junit 测试中获取部分执行时间

java - 如何自动生成新的单元测试ant报告

java - JUnit 测试方法失败

grails - 在Grails JUnit测试案例中记录信息的正确方法是什么?

java - 使用 Mockito 模拟 Hibernate 的 SessionFactory 时测试失败

java - JUnit 测试后多线程应用程序将无法运行

java - JUnit/Mockito 测试因奇怪的原因失败

java - 为什么 Junit 测试仅支持不完全重写 fork?

java - Mockito.verify 和 Mockito.doNothing 在 Junit 测试用例中不起作用

java - 模拟实例在@Mock 注释后为空