使用 mockito 对插入方法进行单元测试
Posted
技术标签:
【中文标题】使用 mockito 对插入方法进行单元测试【英文标题】:unit test for insertion method using mockito 【发布时间】:2017-06-13 04:41:48 【问题描述】:我在插入方法的单元测试中遇到了问题,虽然我使用的是模拟对象,但数据是插入到数据库中的,请问这是什么问题?
这里是方法的源代码
public void InsertPersonalData(PersonalData personaldata) throws SQLException, DAOException, ClassNotFoundException
try
PreparedStatement psmt = mysqlConnection.getPreparedStatement("INSERT INTO personal_data values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
psmt.setString(1, personaldata.getiD());
psmt.setString(2, personaldata.getPatientName());
psmt.setString(3, personaldata.getBirthDate());
psmt.setString(4, personaldata.getPlaceOfBirth());
psmt.setString(5, personaldata.getGender());
psmt.setString(6, personaldata.getNationality());
psmt.setString(7, personaldata.getCurrentAddress());
psmt.setString(8, personaldata.getCityAddress());
psmt.setString(9, personaldata.getMaritalStatus());
psmt.setString(10, personaldata.getOffspring());
psmt.setString(11, personaldata.getAgeOfYoungestOffspring());
psmt.setString(12, personaldata.getWorkNature());
psmt.setString(13, personaldata.getPhoneNumber());
psmt.setString(14, personaldata.geteMail());
psmt.executeUpdate();
catch (SQLException e)
throw new DAOException(e);
这是我使用模拟的方式
@RunWith(MockitoJUnitRunner.class)
public class PersonalDataDaoTest
public PersonalData newpd;
@Mock
Connection conn;
@Mock
PreparedStatement psmt;
@InjectMocks
PersonalDataDao newDAO = new PersonalDataDao();
测试代码:
@Test
public void HappyTestForInsert() throws SQLException, DAOException, ClassNotFoundException
when(conn.prepareStatement(anyString())).thenReturn(psmt);
//ArgumentCaptor<Integer> intcaptor = ArgumentCaptor.forClass(int.class);
ArgumentCaptor<String> stringcaptor = ArgumentCaptor.forClass(String.class);
String id = "11";
String patientName = "yara";
String birthDate = "2001-12-5";
String placeOfBirth = "cairo";
String gender = "female";
String nationality = "egyptian";
String currentAddress = "cairo";
String cityAddress = "cairo";
String maritalStatus = "married";
String offspring = "1";
String ageOfYoungestOffspring = "2";
String workNature = "teacher";
String phoneNumber = "0324324234";
String eMail = "yara@hotmail.com";
PersonalData p = new PersonalData(id, patientName, birthDate, placeOfBirth, gender, nationality, currentAddress, cityAddress, maritalStatus, offspring, ageOfYoungestOffspring, workNature, phoneNumber, eMail);
newDAO.InsertPersonalData(p);
//verify(psmt, times(1)).setInt(anyInt(), intcaptor.capture());
verify(psmt, times(14)).setString(anyInt(), stringcaptor.capture());
Assert.assertTrue(stringcaptor.getAllValues().get(0).equals(id));
Assert.assertTrue(stringcaptor.getAllValues().get(1).equals(patientName));
Assert.assertTrue(stringcaptor.getAllValues().get(2).equals(birthDate));
Assert.assertTrue(stringcaptor.getAllValues().get(3).equals(placeOfBirth));
Assert.assertTrue(stringcaptor.getAllValues().get(4).equals(gender));
Assert.assertTrue(stringcaptor.getAllValues().get(5).equals(nationality));
Assert.assertTrue(stringcaptor.getAllValues().get(6).equals(currentAddress));
Assert.assertTrue(stringcaptor.getAllValues().get(7).equals(cityAddress));
Assert.assertTrue(stringcaptor.getAllValues().get(8).equals(maritalStatus));
Assert.assertTrue(stringcaptor.getAllValues().get(9).equals(offspring));
Assert.assertTrue(stringcaptor.getAllValues().get(10).equals(ageOfYoungestOffspring));
Assert.assertTrue(stringcaptor.getAllValues().get(11).equals(workNature));
Assert.assertTrue(stringcaptor.getAllValues().get(12).equals(phoneNumber));
Assert.assertTrue(stringcaptor.getAllValues().get(13).equals(eMail));
【问题讨论】:
请不要将代码段添加为图片,而是在您的帖子中包含实际代码。 我已经编辑过了 :) 插入发生在方法InsertPersonalData
中。根据您的测试设置,您不是在模拟PersonalDataDAO
,而是在对其进行测试,因此执行插入。
但是DAO类中的查询所以我使用了模拟,我该怎么办?
【参考方案1】:
您正在尝试验证准备好的语句在您的测试中的用法。您的代码设置方式不起作用,因为PreparedStatement
的实例是在您正在测试的方法中创建的:InsertPersonalData
。
但是您可以修改您的代码,使其变得可测试。第一步是将PreparedStatement
的创建移到一个单独的类中,然后可以在您的测试中模拟:
public class StatementProvider
public PreparedStatement createInsertStatementForPersonalData()
return PreparedStatement psmt = MysqlConnection.getPreparedStatement("INSERT INTO personal_data values(?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
接下来您更新您的PersonalDataDao
以使用StatementProvider
:
public class PersonalDataDao
private StatementProvider statementProvider;
// Constructor and other methods ommitted
public void InsertPersonalData(PersonalData personaldata) throws SQLException, DAOException, ClassNotFoundException
try
PreparedStatement psmt = statementProvider.createInsertStatementForPersonalData();
psmt.setString(1, personaldata.getiD());
psmt.setString(2, personaldata.getPatientName());
psmt.setString(3, personaldata.getBirthDate());
psmt.setString(4, personaldata.getPlaceOfBirth());
psmt.setString(5, personaldata.getGender());
psmt.setString(6, personaldata.getNationality());
psmt.setString(7, personaldata.getCurrentAddress());
psmt.setString(8, personaldata.getCityAddress());
psmt.setString(9, personaldata.getMaritalStatus());
psmt.setString(10, personaldata.getOffspring());
psmt.setString(11, personaldata.getAgeOfYoungestOffspring());
psmt.setString(12, personaldata.getWorkNature());
psmt.setString(13, personaldata.getPhoneNumber());
psmt.setString(14, personaldata.geteMail());
psmt.executeUpdate();
catch (SQLException e)
throw new DAOException(e);
然后你的测试看起来像这样:
@RunWith(MockitoJUnitRunner.class)
public class PersonalDataDaoTest
@Mock
private PreparedStatement psmt;
@Mock
private StatmentProvider statementProvider;
@InjectMocks
private PersonalDataDao newDAO; // This is the class under test
@Test
public void HappyTestForInsert() throws SQLException, DAOException, ClassNotFoundException
when(statementProvider.createInsertStatementForPersonalData()).thenReturn(psmt);
//ArgumentCaptor<Integer> intcaptor = ArgumentCaptor.forClass(int.class);
ArgumentCaptor<String> stringcaptor = ArgumentCaptor.forClass(String.class);
String id = "11";
String patientName = "yara";
String birthDate = "2001-12-5";
String placeOfBirth = "cairo";
String gender = "female";
String nationality = "egyptian";
String currentAddress = "cairo";
String cityAddress = "cairo";
String maritalStatus = "married";
String offspring = "1";
String ageOfYoungestOffspring = "2";
String workNature = "teacher";
String phoneNumber = "0324324234";
String eMail = "yara@hotmail.com";
PersonalData p = new PersonalData(id, patientName, birthDate, placeOfBirth, gender, nationality, currentAddress, cityAddress, maritalStatus, offspring, ageOfYoungestOffspring, workNature, phoneNumber, eMail);
newDAO.InsertPersonalData(p);
//verify(psmt, times(1)).setInt(anyInt(), intcaptor.capture());
verify(psmt, times(14)).setString(anyInt(), stringcaptor.capture());
Assert.assertTrue(stringcaptor.getAllValues().get(0).equals(id));
Assert.assertTrue(stringcaptor.getAllValues().get(1).equals(patientName));
Assert.assertTrue(stringcaptor.getAllValues().get(2).equals(birthDate));
Assert.assertTrue(stringcaptor.getAllValues().get(3).equals(placeOfBirth));
Assert.assertTrue(stringcaptor.getAllValues().get(4).equals(gender));
Assert.assertTrue(stringcaptor.getAllValues().get(5).equals(nationality));
Assert.assertTrue(stringcaptor.getAllValues().get(6).equals(currentAddress));
Assert.assertTrue(stringcaptor.getAllValues().get(7).equals(cityAddress));
Assert.assertTrue(stringcaptor.getAllValues().get(8).equals(maritalStatus));
Assert.assertTrue(stringcaptor.getAllValues().get(9).equals(offspring));
Assert.assertTrue(stringcaptor.getAllValues().get(10).equals(ageOfYoungestOffspring));
Assert.assertTrue(stringcaptor.getAllValues().get(11).equals(workNature));
Assert.assertTrue(stringcaptor.getAllValues().get(12).equals(phoneNumber));
Assert.assertTrue(stringcaptor.getAllValues().get(13).equals(eMail));
【讨论】:
是否可以在 StatementProvider 类中返回多个查询,因为我有多个类要以相同的方式进行测试? 当您在测试方法中模拟返回的模拟对象时,您可以有多个测试方法返回不同的模拟。我希望您对StatementProvider
的实现有几种方法,每种方法一种PrepraredStatement
。以上是关于使用 mockito 对插入方法进行单元测试的主要内容,如果未能解决你的问题,请参考以下文章