如何编写忽略数据库活动的 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.merge
和 em.persist
活动。
当我尝试使用 MockitoJUnitRunner
作为 @GauravRai1512
首选时,我执行了我的测试用例,但程序终止了,因此我无法获得结果 ArrayLists.
Refer this image
您可以使用模拟数据库调用。您可以使用 Jmockit 编写测试用例,您可以在其中模拟数据库调用,这将阻止数据库中的保存或更新操作。
你可以从http://jmockit.github.io/tutorial/Introduction.html
学习编写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
对象,仅用于测试,或者使用模拟数据库对象,然后您可以在其中准确定义如何响应每个 merge
、save
、update
和类似操作。如果 PaymentService
对象不允许这样做,那么应该对其进行重新设计,使其接受一个 Database/Connection 作为参数,这将是 运行 时正常的 @Autowired
注入参数在生产中,但您可以在测试时手动实例化。这将是一个适当的测试,因为您将验证 setPaidStatusList
中的其余逻辑,但您实际上并没有访问数据库来实现它。
以下是我的测试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.merge
和 em.persist
活动。
当我尝试使用 MockitoJUnitRunner
作为 @GauravRai1512
首选时,我执行了我的测试用例,但程序终止了,因此我无法获得结果 ArrayLists.
Refer this image
您可以使用模拟数据库调用。您可以使用 Jmockit 编写测试用例,您可以在其中模拟数据库调用,这将阻止数据库中的保存或更新操作。
你可以从http://jmockit.github.io/tutorial/Introduction.html
学习编写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
对象,仅用于测试,或者使用模拟数据库对象,然后您可以在其中准确定义如何响应每个merge
、save
、update
和类似操作。如果PaymentService
对象不允许这样做,那么应该对其进行重新设计,使其接受一个 Database/Connection 作为参数,这将是 运行 时正常的@Autowired
注入参数在生产中,但您可以在测试时手动实例化。这将是一个适当的测试,因为您将验证setPaidStatusList
中的其余逻辑,但您实际上并没有访问数据库来实现它。