我目前正在使用以下方法和单元测试方法。我认为测试可以/应该分解为更多测试,但我不确定要为此编写多少测试或更重要的部分是什么,特别是考虑到该方法处理建立Connection
,使用sql查询等...感谢所有帮助。
JAVA方法:
public static ArrayList<HashMap<String, String>> executeSelect(
Connection conn, Statement stmt, Query query) {
ResultSet rs = null;
ArrayList<HashMap<String, String>> serviceRequests = new ArrayList<HashMap<String, String>>();
try {
long queryStart = System.nanoTime();
rs = stmt.executeQuery(query.getQuery());
long queryEnd = System.nanoTime();
long queryDuration = queryEnd-queryStart;
queryTime = String.valueOf(queryDuration);
while (rs.next()) {
HashMap<String, String> serviceRequestData = new HashMap<>();
if (QueryUtil.hasColumn(rs, "ID")) {
String id = rs.getString("ID");
serviceRequestData.put("ID", id);
}
else{
serviceRequestData.put("ID", " ");
}
if (QueryUtil.hasColumn(rs, "FN_Contact")) {
String firstName = rs.getString("FN_Contact");
serviceRequestData.put("FN_Contact", firstName);
}
else{
serviceRequestData.put("FN_Contact", " ");
}
if (QueryUtil.hasColumn(rs, "LN_Contact")) {
String lastName = rs.getString("LN_Contact");
serviceRequestData.put("LN_Contact", lastName);
}
else{
serviceRequestData.put("LN_Contact", " ");
}
if (QueryUtil.hasColumn(rs, "Notes")) {
String notes = rs.getString("Notes");
serviceRequestData.put("Notes", notes);
}
else{
serviceRequestData.put("Notes", " ");
}
if (QueryUtil.hasColumn(rs, "Email")) {
String email = rs.getString("Email");
serviceRequestData.put("Email", email);
}
else{
serviceRequestData.put("Email", " ");
}
serviceRequests.add(serviceRequestData);
}
} catch (SQLException e) {
e.printStackTrace();
sqlException = true;
}
return serviceRequests;
}
JUnit测试:
@Test
public void testFirstName() {
ArrayList<HashMap<String, String>> testMap = new ArrayList<HashMap<String,String>>();
Connection conn = null;
Statement stmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
String connectionUrl = "jdbc:mysql://localhost:3306/gc_image";
String connectionUser = "root";
String connectionPassword = "GCImage";
conn = DriverManager.getConnection(connectionUrl, connectionUser,
connectionPassword);
conn.
stmt = conn.createStatement();
Query testQuery = new Query();
testQuery
.setQuery("select * from service_request where FN_contact = 'Trevor'");
testMap = QueryController.executeSelect(conn, stmt, testQuery);
assertEquals("Janke", testMap.get(0).get("LN_Contact"));
assertEquals("Hello World", testMap.get(0).get("Notes"));
assertEquals("janke@gmail.com", testMap.get(0).get("Email"));
assertEquals("ID", testMap.get(0).get("7"));
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
stmt.close();
conn.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
答案 0 :(得分:4)
您应该首先确定此测试设置的哪个部分不是测试方法的真正部分;即什么是可以提取到@Before
和@After
方法中的样板。这可能需要您将一些局部变量拉入类变量。这使得每个@Test
方法都不那么冗长,并且允许您专注于测试中的功能。
如果您的代码或测试代码引发意外异常,则接下来应删除所有catch
块,或者使用fail(exception.getMessage())
之类的代码进行测试失败。如果删除它们,将单元测试的方法签名更改为throws Exception
就足够了,以便在抛出异常时通常会失败。就像现在一样,你可能完全无法连接到你的设置中的数据库,Junit测试仍然会变绿!
理想情况下,您有一个涵盖每个if...else
块的单元测试。这会给你10个测试。在那些中,焦点(Assert
)将确认serviceRequests
中是否存在找到/未找到的值。您还应该测试您的异常处理,因此您需要一个强制SQLException
被捕获的测试。
我最后建议,为了减少开销,您可以考虑使用模拟框架(例如Mockito)来完全删除数据库I / O.这个SO question有一些模拟数据库的好例子。
我注意到executeSelect()
中有一些可以修复的快速内容:
Connection
参数 - 它未被使用,因为Statement
已经实例化。serviceRequests
从ArrayList<HashMap<String, String>>
更改为List<Map<String, String>>
。在许多资源中,Josh Bloch的Effective Java是这个主题的一个很好的参考。 您可以通过将以下代码移动到另一个方法中来进一步简化此方法 - 这将使测试更加简单:
long queryStart = System.nanoTime();
rs = stmt.executeQuery(query.getQuery());
long queryEnd = System.nanoTime();
long queryDuration = queryEnd-queryStart;
queryTime = String.valueOf(queryDuration);
然后只将ResultSet
传递给executeSelect()
...或者将其重命名为:)。