使用 JUnit 和 Mockito 对 DAO 类进行单元测试
Posted
技术标签:
【中文标题】使用 JUnit 和 Mockito 对 DAO 类进行单元测试【英文标题】:Unit testing of DAO classes using JUnit and Mockito 【发布时间】:2020-01-17 17:40:43 【问题描述】:我有 DaoImpl 类:
public class MessageTypeDaoImpl implements MessageTypeDao
public int[] createMessageTypes(final List<MessageType> messageTypes)
String sql = "INSERT INTO MSG_TYPE VALUES(?, ?)";
return jdbcTemplate.batchUpdate(sql, new BatchPreparedStatementSetter()
public void setValues(PreparedStatement ps, int i) throws SQLException
MessageType messageType = messageTypes.get(i);
ps.setString(1, messageType.getMessageId());
ps.setString(2, messageType.getMessageName());
public int getBatchSize()
return messageTypes.size();
);
我的测试:
@RunWith(MockitoJUnitRunner.class)
public class MessageTypeDaoImplTest
@Mock
private JdbcTemplate jdbcTemplate;
@Spy
@InjectMocks
MessageTypeDaoImpl messageTypeDaoImpl;
@Before
public void setUp()
MockitoAnnotations.initMocks(this);
@Test
public void createMessageTypes()
int[] returnCount = new int[1];
List<MessageType> messageTypeList = new ArrayList<MessageType>();
messageTypeList.add(getSampleMessageType());
messageTypeDaoImpl.createMessageTypes(messageTypeList);
doReturn(returnCount).when(messageTypeDaoImpl).createMessageTypes(messageTypeList);
assertEquals(returnCount, messageTypeDaoImpl.createMessageTypes(messageTypeList));
public MessageType getSampleMessageType()
return new MessageType("messageTypeId", "messageTypeName");
测试成功,但是当我运行 junit 覆盖测试时,它显示 public void setValues()
方法没有被覆盖,因此我的整体单元测试行覆盖率低于要求。我们可以涵盖那部分吗?如果是,那么我们如何做到这一点?谢谢。
【问题讨论】:
不要模拟 JdbcTemplate,使用真实的实例。您的 Spring 容器中可能已经有一个真实的实例。请注意,JdbcTemplate 具有依赖关系,例如:DataSource。您可能需要模拟 DataSource 并将其注入 JdbcTemplate。您可以让 Spring 为您注入 if:在您的单元测试中有一个 DataSource 类型的成员变量,并在其上使用 @MockBean 注释。 在 doReturn().when() 语句之前调用 `messageTypeDaoImpl.createMessageTypes(messageTypeList);` 有什么意义?还有:你为什么在这里使用间谍?似乎您正在将 Mockito 的各种元素拼凑在一起,却不知道它们的实际用途是什么? @GhostCat 我调用了 createMessageTypes,因为如果我不这样做,该方法将不会被调用,并且不会有代码覆盖。我需要确保我的代码覆盖率尽可能高(IntelliJ IDE 中的类 % 和行 % 覆盖率)。关于 Spy 注释,我在调用方法时遇到了问题(再次用于代码覆盖),*** 上有人说我们可以使实例接近真实实例(或半模拟)并调用该方法。我之前没有做过那么多的单元测试,更不用说mockito了。所以我想了解如何让它协同工作。 【参考方案1】:试试下面的代码spinet。我也会介绍代码。我从头到尾检查了它,它起作用了。
int[] batchInsert=new int[] 1,2;
try
Mockito.doAnswer(invocationOnMock ->
PreparedStatement ps = Mockito.mock(PreparedStatement.class);
BatchPreparedStatementSetter psr = invocationOnMock.getArgument(1);
psr.setValues(ps, 1);
return batchInsert;
).when(jdbcTemplate).batchUpdate(anyString(), Mockito.any(BatchPreparedStatementSetter.class));
【讨论】:
以上是关于使用 JUnit 和 Mockito 对 DAO 类进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章
JUnit 在带有 @Autowired 注释的 Spring Boot 中不起作用
使用 Junit 和 Mockito 嵌套异常问题测试 POST Api