Java 如何在Junit(Springboot)中模拟BeanPropertyRowMapper?
我正在为电子邮件DAO层编写一个测试用例。这有点像:Java 如何在Junit(Springboot)中模拟BeanPropertyRowMapper?,java,unit-testing,junit,mockito,jdbctemplate,Java,Unit Testing,Junit,Mockito,Jdbctemplate,我正在为电子邮件DAO层编写一个测试用例。这有点像: @Repository @PropertySource({ "classpath:/query.properties" }) public class DaoLayerImpl implements DaoLayerDao { /** The jdbc template. */ @Qualifier("mariaJdbcTemplate") @Autowired private JdbcTemplate jd
@Repository
@PropertySource({ "classpath:/query.properties" })
public class DaoLayerImpl implements DaoLayerDao {
/** The jdbc template. */
@Qualifier("mariaJdbcTemplate")
@Autowired
private JdbcTemplate jdbcTemplate;
/** The find staged query. */
@Value("${someQuery}")
String someQuery;
@Override
public List<SomeBean> getData() throws MariaDbException {
List<SomeBean> listOfData = new ArrayList<>();
try {
listOfData = jdbcTemplate.query(someQuery,
new BeanPropertyRowMapper<SomeBean>(SomeBean.class));
} catch (RuntimeException e) {
logger.error("RuntimeException in ", e);
}
return listOfData;
}
}
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.any;
...
Mockito.when(jdbcTemplate.query(eq("someQuery"),
any(BeanPropertyRowMapper.class)).thenReturn(....);
@存储库
@PropertySource({“classpath:/query.properties”})
公共类DaoLayerImpl实现DaoLayerDao{
/**jdbc模板*/
@限定词(“mariaJdbcTemplate”)
@自动连线
私有JdbcTemplate JdbcTemplate;
/**查找暂存查询*/
@值(“${someQuery}”)
字符串查询;
@凌驾
public List getData()抛出MariadBeException{
List listOfData=new ArrayList();
试一试{
listOfData=jdbcTemplate.query(someQuery,
新的BeanPropertyRowMapper(SomeBean.class));
}捕获(运行时异常e){
logger.error(“e中的RuntimeException”);
}
返回数据列表;
}
}
该层的测试用例为:
@RunWith(SpringRunner.class)
@ActiveProfiles("test")
@PropertySource("classpath:application-test.properties")
public class EmailDaoLayerTest {
@MockBean
JdbcTemplate jdbcTemplate;
@InjectMocks
DaoLayerImpl dao;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
jdbcTemplate = Mockito.mock(JdbcTemplate.someQuery);
ReflectionTestUtils.setField(dao, "jdbcTemplate", jdbcTemplate);
}
@Test
public void testCaseForGetData() throws Exception {
List<SomeBean> beanObject = new ArrayList<>();
beanObject.add(new SomeBean());
beanObject.add(new SomeBean());
beanObject.add(new SomeBean());
System.out.println(beanObject.size()); // 3
when(jdbcTemplate.query("someQuery",
new BeanPropertyRowMapper<SomeBean>(SomeBean.class))).thenReturn(beanObject);
List<SomeBean> obj = dao.getData();
System.out.println(obj.size()); //0
System.out.println("Done");
}
}
@RunWith(SpringRunner.class)
@ActiveProfiles(“测试”)
@PropertySource(“类路径:application test.properties”)
公共类EmailDaoLayerTest{
@蚕豆
jdbc模板jdbc模板;
@注射模拟
道与道;
@以前
公共作废设置(){
initMocks(this);
jdbcTemplate=Mockito.mock(jdbcTemplate.someQuery);
setField(dao,“jdbcTemplate”,jdbcTemplate);
}
@试验
public void testCaseForGetData()引发异常{
List beanObject=new ArrayList();
添加(newsomebean());
添加(newsomebean());
添加(newsomebean());
System.out.println(beanObject.size());//3
当(jdbcTemplate.query)(“someQuery”,
新BeanPropertyRowMapper(SomeBean.class)),然后返回(beanObject);
List obj=dao.getData();
System.out.println(obj.size());//0
系统输出打印项次(“完成”);
}
}
模拟后,对象大小显示为0,而不是3。返回前对象的大小为3。当我实际命中DAO时,对象的大小为0,而我已经使用when-then模拟了jdbc模板
模拟Bean属性行映射器类的正确方法是什么?让我回答这个问题,然后批评你的方法,也许这有助于更好地理解最终的解决方案 所以要回答你的问题: 从技术上讲,您可能可以执行以下操作:
@Repository
@PropertySource({ "classpath:/query.properties" })
public class DaoLayerImpl implements DaoLayerDao {
/** The jdbc template. */
@Qualifier("mariaJdbcTemplate")
@Autowired
private JdbcTemplate jdbcTemplate;
/** The find staged query. */
@Value("${someQuery}")
String someQuery;
@Override
public List<SomeBean> getData() throws MariaDbException {
List<SomeBean> listOfData = new ArrayList<>();
try {
listOfData = jdbcTemplate.query(someQuery,
new BeanPropertyRowMapper<SomeBean>(SomeBean.class));
} catch (RuntimeException e) {
logger.error("RuntimeException in ", e);
}
return listOfData;
}
}
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.any;
...
Mockito.when(jdbcTemplate.query(eq("someQuery"),
any(BeanPropertyRowMapper.class)).thenReturn(....);
然而,你应该问问自己,你到底想在这里测试什么?这里有一个相对昂贵的集成测试,它运行Spring上下文(它与SpringRunner一起工作),并在后台创建许多对象
然而,基于要测试的方法,我看不出有任何“有意义”(有待测试)的代码要测试。您可以测试给定的查询,BeanPropertyRowMapper确实可以将响应转换为SomeBean
的实例,但是您再次模拟它,它并没有真正运行
您可以检查您准备的查询是否针对数据库运行并返回预期的结果,但这里似乎没有准备任何数据库
因此,如果目的是覆盖率,那么是的,您将被覆盖,但是测试不是关于覆盖率,而是关于确保您的代码正常工作。在这种情况下,运行Spring驱动的集成测试(包括应用程序上下文和所有内容)似乎是一种巨大的过度操作,
MockitoRunner
可以完成这项工作在模拟调用函数的参数时尝试使用Mockito.any(类)。例如:对于方法查询,我在(jdbcTemplate.query(Mockito.anyString(),Mockito.eq(newbeanPropertyRowmapper(SomeBean.class)))时尝试使用的第一个参数是Mockito.mock(String.class),第二个参数是Mockito.any(class.class)),然后返回(beanObject);还是一样的结果谢谢你的回复。。。你说的没错。我们建议不要在这里使用H2。因此,为DAO layere编写测试的唯一方法是仅针对代码覆盖率。我已经测试了这个loc:Mockito.when(jdbcTemplate.query(eq(“someQuery”)、any(BeanPropertyRowMapper.class))。然后返回(…);但有一个疑问,您是否建议在这里使用MockitoRunner而不是SpringRunner。我被告知要为我们的企业应用程序编写单元测试。所以MockitoRunner将是最好的方法,对吗?好吧,只要您能涵盖单元测试(mockito runner)做吧。一旦你用spring runner运行,这是一个集成测试,在数量级上总是比单元测试更重、更慢OK分数..!谢谢..!只是想知道你是否能回答这个问题:请查看我对你问题的回答;)