如何编写忽略数据库活动的 JUnit 测试用例

How to write JUnit test cases with ignoring database activities

以下是我的测试class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/ds-context.xml")
@WebAppConfiguration
public class PaidListTest {

    @Autowired
    PaymentService paymentService;

    @Test
    public void getPaidList() {
        List<PaymentGetServiceDO> response = null;
        try {
            response = paymentService.setPaidStatusList();          
            if(response != null && response.size() > 0){
                for(int i = 0; i < response.size(); i++){
                    assertNotNull(response.get(i).getAgentcode());
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在服务调用的 DAO 层 paymentService.setPaidStatusList() 有一些保存和更新数据库活动的操作,比如 em.merge(renewalPoliciesDO);
但我不想在调用测试方法时执行它们,只有在调用实际业务逻辑时才需要调用它们。
如何限制或回滚此处的数据库事务?
服务和 DAO 方法在这里很乏味。不过我已经简化了,供大家参考。
服务方式 if(!updateList.isEmpty()){ HashMap<String,String> recordset = new HashMap<String,String>(); recordset = paymentDAO.setRenewalStatus(updateList); }
DAO 实现

if(paymentUpdateResDO.getPaymentstatus().equalsIgnoreCase("MANUAL") && 
!responseUpdateStatus.getPolicystatusid().equals(renewedStatusId)){
CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
CriteriaQuery<Integer> payQuery = criteriaBuilder.createQuery(Integer.class);
Root<PaymentStatusDO> payRoot = payQuery.from(PaymentStatusDO.class);
payQuery.multiselect(payRoot.get("paymentstatusid"));
payQuery.where(criteriaBuilder.equal(payRoot.get("paymentstatusdescription"), "Manual"));
Integer paymentStatusId = em.createQuery(payQuery).getSingleResult();
insertOldPolicy(responseUpdateStatus);
responseUpdateStatus.setNewpolicyno(paymentUpdateResDO.getNewpolicyno());
responseUpdateStatus.setPreviousstatusid(responseUpdateStatus.getPolicystatusid());
responseUpdateStatus.setPolicystatusid(renewedStatusId);
Timestamp modifiedDate = new Timestamp(System.currentTimeMillis());
responseUpdateStatus.setModifieddatetime(modifiedDate);
responseUpdateStatus.setModifiedby("RPA");
responseUpdateStatus.setPaymentstatusid(paymentStatusId);
responseUpdateStatus.setActiveindicator("Y");
em.merge(responseUpdateStatus);
successRecords++;
}

在我的例子中,我需要结果数组列表,但需要忽略 em.mergeem.persist 活动。

当我尝试使用 MockitoJUnitRunner 作为 @GauravRai1512 首选时,我执行了我的测试用例,但程序终止了,因此我无法获得结果 ArrayLists.


Refer this image

您可以使用模拟数据库调用。您可以使用 Jmockit 编写测试用例,您可以在其中模拟数据库调用,这将阻止数据库中的保存或更新操作。

你可以从http://jmockit.github.io/tutorial/Introduction.html

学习编写jmockit测试用例

https://winterbe.com/posts/2009/08/18/introducing-jmockit/

您应该遵循 Pooja Aggarwal 建议的以下方法。

import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

    @RunWith(MockitoJUnitRunner.class)
    public class PaidListTest {

        @Mock
        PaymentService paymentService;

        @Before
          public void setUp() {
             MockitoAnnotations.initMocks(this);
             mapperObj = new ObjectMapper();
             List<PaymentGetServiceDO> response = new ArrayList<PaymentGetServiceDO>();
}
        @Test
        public void getPaidList() {
            List<PaymentGetServiceDO> response = null;
            try {
                response = paymentService.setPaidStatusList();          
                if(response != null && response.size() > 0){
                    for(int i = 0; i < response.size(); i++){
                        assertNotNull(response.get(i).getAgentcode());
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

此代码不会执行您的保存和更新操作。

正如其他人所说,您可以:

  • 模拟 PaymentService 以便您可以准确定义对它的每次调用要执行的操作。在这种情况下,您只需 return 一个硬编码的 List<PaymentGetServiceDO> 响应,您的测试就可以用它做一些事情。这样做的缺点是,在那种情况下,您并不是 真正地 测试 PaymentService。您只是在查看硬编码数据,然后用它做一些事情。在我看来,这不是一个有效的测试。

  • 或者,您可以使用内存数据库实例化一个 PaymentService 对象,仅用于测试,或者使用模拟数据库对象,然后您可以在其中准确定义如何响应每个 mergesaveupdate 和类似操作。如果 PaymentService 对象不允许这样做,那么应该对其进行重新设计,使其接受一个 Database/Connection 作为参数,这将是 运行 时正常的 @Autowired 注入参数在生产中,但您可以在测试时手动实例化。这将是一个适当的测试,因为您将验证 setPaidStatusList 中的其余逻辑,但您实际上并没有访问数据库来实现它。