Khuôn khổ tốt nhất để tạo các đối tượng giả trong Java là gì? Tại sao? Những ưu và nhược điểm của từng khung là gì?
Khuôn khổ tốt nhất để tạo các đối tượng giả trong Java là gì? Tại sao? Những ưu và nhược điểm của từng khung là gì?
Câu trả lời:
Tôi đã thành công khi sử dụng Mockito .
Khi tôi cố gắng tìm hiểu về JMock và EasyMock, tôi thấy đường cong học tập hơi dốc (mặc dù có lẽ đó chỉ là tôi).
Tôi thích Mockito vì cú pháp đơn giản và rõ ràng của nó mà tôi có thể nắm bắt khá nhanh. Cú pháp tối thiểu được thiết kế để hỗ trợ rất tốt cho các trường hợp phổ biến, mặc dù vài lần tôi cần làm gì đó phức tạp hơn, tôi thấy những gì tôi muốn được hỗ trợ và dễ nắm bắt.
Đây là một ví dụ (được rút ngắn) từ trang chủ Mockito:
import static org.mockito.Mockito.*;
List mockedList = mock(List.class);
mockedList.clear();
verify(mockedList).clear();
Nó không đơn giản hơn thế nhiều.
Nhược điểm lớn duy nhất tôi có thể nghĩ đến là nó sẽ không chế nhạo các phương thức tĩnh.
Tôi là người tạo ra PowerMock nên rõ ràng tôi phải khuyên bạn điều đó! :-)
PowerMock mở rộng cả EasyMock và Mockito với khả năng mô phỏng các phương thức tĩnh , phương thức cuối cùng và thậm chí là riêng tư. Hỗ trợ EasyMock đã hoàn tất, nhưng plugin Mockito cần thêm một số công việc. Chúng tôi đang lên kế hoạch để thêm hỗ trợ JMock là tốt.
PowerMock không có ý định thay thế các khung công tác khác, thay vào đó, nó có thể được sử dụng trong các tình huống khó khăn khi các khung công tác khác không cho phép chế nhạo. PowerMock cũng chứa các tính năng hữu ích khác như chặn các trình khởi tạo và hàm tạo tĩnh .
Các khu vực dự án JMockit chứa rất nhiều thông tin so sánh cho các bộ công cụ mocking hiện hành.
Cụ thể, hãy kiểm tra ma trận so sánh tính năng , bao gồm EasyMock, jMock, Mockito, Unitils Mock, PowerMock, và dĩ nhiên là JMockit. Tôi cố gắng giữ cho nó chính xác và cập nhật, càng nhiều càng tốt.
Tôi đã thành công với JMockit .
Nó khá mới, và do đó, nó hơi thô và chưa được ghi chép đầy đủ. Nó sử dụng ASM để xác định lại động theo mã byte lớp, do đó nó có thể mô phỏng tất cả các phương thức bao gồm tĩnh, riêng, hàm tạo và khởi tạo tĩnh. Ví dụ:
import mockit.Mockit;
...
Mockit.redefineMethods(MyClassWithStaticInit.class,
MyReplacementClass.class);
...
class MyReplacementClass {
public void $init() {...} // replace default constructor
public static void $clinit{...} // replace static initializer
public static void myStatic{...} // replace static method
// etc...
}
Nó cũng có giao diện Expectations cho phép ghi lại các kịch bản / phát lại:
import mockit.Expectations;
import org.testng.annotations.Test;
public class ExpecationsTest {
private MyClass obj;
@Test
public void testFoo() {
new Expectations(true) {
MyClass c;
{
obj = c;
invokeReturning(c.getFoo("foo", false), "bas");
}
};
assert "bas".equals(obj.getFoo("foo", false));
Expectations.assertSatisfied();
}
public static class MyClass {
public String getFoo(String str, boolean bool) {
if (bool) {
return "foo";
} else {
return "bar";
}
}
}
}
Nhược điểm là nó yêu cầu Java 5/6.
Bạn cũng có thể xem thử nghiệm bằng Groovy. Trong Groovy, bạn có thể dễ dàng mô phỏng các giao diện Java bằng cách sử dụng toán tử 'as':
def request = [isUserInRole: { roleName -> roleName == "testRole"}] as HttpServletRequest
Ngoài chức năng cơ bản này, Groovy cung cấp nhiều hơn nữa trên mặt trận chế giễu, bao gồm cả các lớp mạnh mẽ MockFor
và StubFor
đẳng cấp.
Tôi bắt đầu sử dụng giả với EasyMock . Đủ dễ hiểu, nhưng bước phát lại hơi khó chịu. Mockito loại bỏ điều này, cũng có một cú pháp rõ ràng hơn vì có vẻ như khả năng đọc là một trong những mục tiêu chính của nó. Tôi không thể nhấn mạnh đủ tầm quan trọng của việc này, vì hầu hết các nhà phát triển sẽ dành thời gian đọc và duy trì mã hiện có, không tạo ra nó.
Một điều tuyệt vời nữa là các giao diện và các lớp triển khai được xử lý theo cùng một cách, không giống như trong EasyMock, nơi bạn vẫn cần nhớ (và kiểm tra) để sử dụng tiện ích mở rộng lớp EasyMock.
Gần đây tôi đã xem qua JMockit và trong khi danh sách các tính năng giặt là khá toàn diện, tôi nghĩ giá của điều này là mức độ dễ đọc của mã kết quả và phải viết thêm.
Đối với tôi, Mockito đạt đến điểm ngọt ngào, dễ viết và đọc và xử lý hầu hết các tình huống mà hầu hết các mã sẽ yêu cầu. Sử dụng Mockito với PowerMock sẽ là lựa chọn của tôi.
Một điều cần xem xét là công cụ bạn sẽ chọn nếu bạn tự phát triển hoặc trong một nhóm nhỏ chặt chẽ, có thể không phải là công cụ tốt nhất để có được cho một công ty lớn với các nhà phát triển có trình độ kỹ năng khác nhau. Dễ đọc, dễ sử dụng và đơn giản sẽ cần xem xét nhiều hơn trong trường hợp sau. Không có ý nghĩa trong việc có được khuôn khổ chế giễu cuối cùng nếu nhiều người cuối cùng không sử dụng nó hoặc không duy trì các bài kiểm tra.
Chúng tôi đang sử dụng EasyMock và EasyMock Class Extension trong công việc và khá hài lòng với nó. Về cơ bản nó cung cấp cho bạn mọi thứ bạn cần. Hãy xem tài liệu này, có một ví dụ rất hay cho bạn thấy tất cả các tính năng của EasyMock.
Tôi đã sử dụng JMock sớm. Tôi đã thử Mockito tại dự án cuối cùng của tôi và thích nó. Ngắn gọn hơn, sạch sẽ hơn. PowerMock đáp ứng tất cả các nhu cầu vắng mặt trong Mockito, chẳng hạn như chế nhạo mã tĩnh, chế nhạo một tạo cá thể, chế nhạo các lớp và phương thức cuối cùng. Vì vậy, tôi có tất cả những gì tôi cần để thực hiện công việc của mình.
Tôi thích JMock vì bạn có thể thiết lập kỳ vọng. Điều này hoàn toàn khác với việc kiểm tra nếu một phương thức được gọi là tìm thấy trong một số thư viện giả. Sử dụng JMock bạn có thể viết những kỳ vọng rất tinh vi. Xem jmock cheat-sheat .
Vâng, Mockito là một khuôn khổ tuyệt vời. Tôi sử dụng nó cùng với hamcrest và Google guice để thiết lập các bài kiểm tra của mình.
Giải pháp tốt nhất để chế nhạo là để máy thực hiện mọi công việc với thử nghiệm dựa trên đặc tả tự động. Đối với Java, hãy xem ScalaCheck và khung Reductio có trong thư viện Java Chức năng . Với các khung kiểm tra dựa trên đặc tả tự động, bạn tự động cung cấp một đặc tả của phương thức được kiểm tra (một thuộc tính về nó phải đúng) và khung tự động tạo ra các kiểm tra cũng như các đối tượng giả.
Ví dụ, thuộc tính sau kiểm tra phương thức Math.sqrt để xem căn bậc hai của bất kỳ số dương nào n bình phương có bằng n không.
val propSqrt = forAll { (n: Int) => (n >= 0) ==> scala.Math.sqrt(n*n) == n }
Khi bạn gọi propSqrt.check()
, ScalaCheck tạo ra hàng trăm số nguyên và kiểm tra từng thuộc tính của bạn, cũng tự động đảm bảo rằng các trường hợp cạnh được bảo vệ tốt.
Mặc dù ScalaCheck được viết bằng Scala và yêu cầu Trình biên dịch Scala, thật dễ dàng để kiểm tra mã Java với nó. Khung Reductio trong Java chức năng là một triển khai Java thuần túy của các khái niệm tương tự.
Mockito cũng cung cấp tùy chọn các phương pháp stubbing, phù hợp với đối số (như anyInt () và anyString ()), xác minh số của lời gọi (lần (3), atLeastOnce (), không bao giờ ()), và nhiều hơn nữa .
Tôi cũng thấy rằng Mockito đơn giản và sạch sẽ .
Một điều tôi không thích ở Mockito là bạn không thể bỏ qua các phương thức tĩnh .
Đối với một cái gì đó hơi khác một chút, bạn có thể sử dụng JRuby và Mocha được kết hợp trong JtestR để viết các bài kiểm tra cho mã Java của bạn bằng Ruby biểu cảm và cô đọng. Có một số ví dụ chế giễu hữu ích với JtestR ở đây . Một lợi thế của phương pháp này là việc chế nhạo các lớp bê tông rất đơn giản.
Tôi bắt đầu sử dụng giả thông qua JMock, nhưng cuối cùng đã chuyển sang sử dụng EasyMock. EasyMock chỉ như vậy, --easier-- và cung cấp một cú pháp cảm thấy tự nhiên hơn. Tôi đã không chuyển từ đó.