【问题标题】:How to write JUnit test cases with ignoring database activities如何编写忽略数据库活动的 JUnit 测试用例
【发布时间】:2018-11-13 04:24:01
【问题描述】:

以下是我的测试类

@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。


参考这张图片

【问题讨论】:

  • 你已经写了 assertNotNull(response.get(i).getAgentcode()) 这个所以它只会给你成功和失败。它不会给你任何价值,因为 junit 用于测试你的代码逻辑行为。
  • 我应该删除 assertNotNull() 以运行我的方法吗?我也试过了。但它仍然终止。

标签: java hibernate junit testcase


【解决方案1】:

您应该按照 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();
            }
        }
    }

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

【讨论】:

  • 我在尝试这个方法时遇到了这个异常:org.mockito.exceptions.base.MockitoException: Field 'paymentService' annotated with @InjectMocks is null. 请确保实例是在之前 MockitoAnnotations.initMocks();正确用法示例:class SomeTest { @InjectMocks private Foo foo = new Foo(); @Before public void setUp() { MockitoAnnotations.initMock(this);
  • @VengatJoy 你能再检查一下吗?我已经更改了代码。你也可以分享 setPaidStatusList() 代码。
  • 你能用 setPaidStatusList() 方法共享 paymentService 类吗?
  • @VengatJoy 你写了 assertNotNull(response.get(i).getAgentcode() 这个所以它只会给你成功和失败。它不会给你任何价值,因为 junit 是用来测试你的代码逻辑行为。
  • @VengatJoy,因为您的问题已经解决,所以请您投票并接受这个答案。
【解决方案2】:

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

你可以从http://jmockit.github.io/tutorial/Introduction.html学习编写jmockit测试用例

或者

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

【讨论】:

    【解决方案3】:

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

    • 模拟PaymentService,以便您可以准确定义每次调用它时要执行的操作。在这种情况下,您只需返回一个硬编码的List&lt;PaymentGetServiceDO&gt; 响应,您的测试就可以对此进行处理。这样做的缺点是,在这种情况下,您并没有真正测试PaymentService。您只是在查看硬编码的数据,并对其进行处理。在我看来,这不是一个有效的测试。

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

    【讨论】:

    • 你说第一个选项不是正确的测试方法吗?但我需要执行硬编码的 ArrayList 响应。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多