Tôi đang kiểm tra đơn vị một lớp mà tôi cần một khoảng thời gian nhất định để vượt qua trước khi tôi có thể kiểm tra kết quả. Cụ thể tôi cần x phút để vượt qua trước khi tôi có thể biết liệu bài kiểm tra có hiệu quả hay không. Tôi đã đọc điều đó trong thử nghiệm đơn vị, chúng ta nên kiểm tra giao diện chứ không phải thực hiện, vì vậy chúng ta không nên truy cập vào biến riêng, nhưng ngoài việc đặt một giấc ngủ vào bài kiểm tra đơn vị của mình, tôi không biết cách kiểm tra mà không sửa đổi biến riêng.Làm thế nào để kiểm tra việc vượt qua thời gian trong thử nghiệm jUnit mà không cần truy cập các biến riêng tư?
thử nghiệm của tôi được thiết lập như thế này:
@Test
public void testClearSession() {
final int timeout = 1;
final String sessionId = "test";
sessionMgr.setTimeout(timeout);
try {
sessionMgr.createSession(sessionId);
} catch (Exception e) {
e.printStackTrace();
}
DBSession session = sessionMgr.getSession(sessionId);
sessionMgr.clearSessions();
assertNotNull(sessionMgr.getSession(sessionId));
Calendar accessTime = Calendar.getInstance();
accessTime.add(Calendar.MINUTE, - timeout - 1);
session.setAccessTime(accessTime.getTime()); // MODIFY PRIVATE VARIABLE VIA PROTECTED SETTER
sessionMgr.clearSessions();
assertNull(sessionMgr.getSession(sessionId));
}
Có thể kiểm tra điều này không phải là sửa đổi biến tin accessTime (thông qua việc tạo ra các setter setAccessTime hoặc phản chiếu), hoặc chèn một giấc ngủ trong các thử nghiệm đơn vị ?
EDIT 11 tháng Tư năm 2012
Tôi đặc biệt cố gắng để kiểm tra rằng đối tượng SessionManager tôi xóa phiên sau một thời gian nhất định đã trôi qua. Cơ sở dữ liệu tôi đang kết nối sẽ thả các kết nối sau một khoảng thời gian cố định. Khi tôi đến gần thời gian chờ đó, đối tượng SessionManager sẽ xóa các phiên bằng cách gọi thủ tục "hoàn tất phiên" trên cơ sở dữ liệu và xóa các phiên khỏi danh sách nội bộ của nó.
Đối tượng SessionManager được thiết kế để chạy trong một chuỗi riêng biệt. Mã này tôi đang thử nghiệm trông như sau:
public synchronized void clearSessions() {
log.debug("clearSessions()");
Calendar cal = Calendar.getInstance();
cal.add(Calendar.MINUTE, - timeout);
Iterator<Entry<String, DBSession>> entries = sessionList.entrySet().iterator();
while (entries.hasNext()) {
Entry<String, DBSession> entry = entries.next();
DBSession session = entry.getValue();
if (session.getAccessTime().before(cal.getTime())) {
// close connection
try {
connMgr.closeconn(session.getConnection(), entry.getKey());
} catch (Exception e) {
e.printStackTrace();
}
entries.remove();
}
}
}
các cuộc gọi đến connMgr (ConnectionManager đối tượng) là một chút phức tạp, nhưng tôi đang trong quá trình mã di sản refactoring và nó là nó là gì vào lúc này. Đối tượng Session lưu trữ kết nối đến cơ sở dữ liệu cũng như một số dữ liệu liên quan.
Một lưu ý phụ: kiểm tra đơn vị thường không nên kiểm tra bất cứ điều gì hoạt động trong nền (trong các chủ đề riêng biệt). Vì vậy, bạn có thể tách logic và chạy nó trong một chủ đề khác. Cái đầu tiên sau đó có thể dễ dàng được kiểm tra bởi các bài kiểm tra đơn vị, và thứ hai - theo các bài kiểm tra chức năng/chấp nhận – zerkms
Mã mà bạn đang kiểm tra gọi là 'System.getCurrentTimeMillis()' (hoặc một cái gì đó tương đương như 'new Date()')? Nếu vậy, đây là một cái gì đó của một mô hình chống thử nghiệm; bạn muốn ủy quyền điều này cho một lớp "nguồn thời gian", mà bạn có thể tiêm. Sau đó, bạn có thể thực hiện các thử nghiệm của mình bằng nguồn thời gian giả. Nếu bạn có thể đăng nguồn mà bạn đang cố gắng kiểm tra, tôi có thể giúp bạn hiểu cách làm những gì tôi đề xuất. –
@DavidWallace - Tôi cho rằng GetInstance là cuộc gọi đó. JavaDocs xác nhận phương thức getInstance của Lịch trả về một đối tượng Lịch có các trường thời gian đã được khởi tạo với ngày tháng và thời gian hiện tại: ' – Gishu