So sánh giữa Mockito vs JMockit - tại sao Mockito được bình chọn tốt hơn JMockit? [đóng cửa]


124

Tôi đang điều tra khung mô phỏng nào sẽ sử dụng cho dự án của mình và đã thu hẹp nó xuống JMockitMockito .

Tôi nhận thấy rằng Mockito đã được bình chọn là " khung giả lập tốt nhất cho Java " trên Stackoverflow.
Khi so sánh tính năng trên JMockit 's ' Mocking Tool So sánh Matrix ' có vẻ như JMockit có nhiều tính năng khác nhau.

Có ai có bất kỳ thông tin cụ thể nào (không phải ý kiến) về những gì Mockito có thể làm mà không thể đạt được với JMockit và ngược lại không?


2
có lẽ khả năng sử dụng tốt hơn cho mockito, btw Tôi không nghĩ JMockit trưởng thành hơn Mockito ...
Alois Cochard

42
Đánh giá bằng số phiếu bầu, NGHIÊM TÚC các câu trả lời cho câu hỏi này được cộng đồng tìm kiếm rất nhiều. Điều đó có nghĩa là chiến lược trực giao của trang web này đã khiến câu hỏi này bị đóng lại cần phải xem xét lại một cách nghiêm túc - trong đó trang web này thường xuyên tự đặt chân vào việc có thể đưa ra câu trả lời cần thiết bằng cách rơi vào tính trực giao bị sai lệch của nó. Không nhận ra rằng trong phân tích biểu đồ của cây, có nhiều cách để xem tính trực giao của cây như có các nút. Có lẽ tính trực giao của trang web này, thay vì câu hỏi, bị sai lệch.
Phúc cho Geek

9
+1 vì không đóng. Những câu trả lời có tấn giá trị. Chọn một công nghệ không dễ dàng và những câu hỏi này có thể tiết kiệm rất nhiều thời gian. Thật vậy, có thể không có câu trả lời đúng nhưng StackOverflow nên chứa các câu hỏi mà không cần gạt.
mhstnsc

6
Tôi sẽ thêm hỗ trợ của mình cho những người nói rằng đóng cái này là "không mang tính xây dựng" là vô lý. Các câu trả lời được cung cấp ở đây được hỗ trợ bởi "sự kiện, tài liệu tham khảo và / hoặc chuyên môn." Một câu hỏi trong lĩnh vực công nghệ không thu hút được một số "cuộc tranh luận, bỏ phiếu hoặc thảo luận mở rộng" thường không đáng để hỏi. Hơn nữa, việc cung cấp sự thật và chuyên môn dựa trên những kinh nghiệm khác nhau - và những khác biệt đó sẽ dẫn đến tranh luận và thảo luận mở rộng.
Jeff Nyman

@Alois - bạn có thể đưa ra ví dụ cụ thể trong đó JMockit trông kém trưởng thành hơn Mockito không?
NitinS

Câu trả lời:


140

Cập nhật tháng 9 năm 2019: Khung mô phỏng duy nhất được hỗ trợ (theo mặc định) bởi Spring BootMockito . Nếu bạn sử dụng Spring, câu trả lời là khá rõ ràng.


Tôi muốn nói rằng cuộc cạnh tranh là giữa JMockitPowerMock , sau đó là Mockito .

Tôi sẽ bỏ jMock và EasyMock "đơn giản" vì họ chỉ sử dụng proxy & CGLIB và không sử dụng công cụ Java 5 như các khung công tác mới hơn.

jMock cũng không có bản phát hành ổn định trong hơn 4 năm. jMock 2.6.0 cần 2 năm để chuyển từ RC1 sang RC2, và sau đó 2 năm nữa trước khi nó thực sự được phát hành.

Về Proxy & CGLIB so với thiết bị:

(EasyMock và jMock) dựa trên java.lang.reflect.Proxy, yêu cầu giao diện phải được thực hiện. Ngoài ra, chúng hỗ trợ việc tạo các đối tượng giả cho các lớp thông qua việc tạo lớp con CGLIB. Do đó, các lớp đã nói không thể là cuối cùng và chỉ các phương thức cá thể có thể bị quá tải mới có thể bị chế giễu. Tuy nhiên, quan trọng nhất là khi sử dụng các công cụ này, các phụ thuộc của mã được kiểm tra (nghĩa là các đối tượng của các lớp khác mà một lớp được kiểm tra phụ thuộc) phải được kiểm soát bằng các phép thử, để các trường hợp giả có thể được truyền cho các máy khách của những phụ thuộc đó. Do đó, các phụ thuộc đơn giản không thể được khởi tạo với toán tử mới trong lớp máy khách mà chúng ta muốn viết các bài kiểm tra đơn vị.

Cuối cùng, các hạn chế kỹ thuật của các công cụ chế tạo thông thường áp đặt các hạn chế thiết kế sau đối với mã sản xuất:

  1. Mỗi lớp có thể cần được chế giễu trong một bài kiểm tra phải thực hiện một giao diện riêng hoặc không phải là cuối cùng.
  2. Các phụ thuộc của từng lớp được kiểm tra phải được lấy thông qua các phương thức tạo cá thể có thể định cấu hình (nhà máy hoặc Bộ định vị dịch vụ) hoặc được đưa ra để tiêm phụ thuộc. Mặt khác, các thử nghiệm đơn vị sẽ không thể vượt qua các triển khai giả định của các phụ thuộc cho đơn vị được thử nghiệm.
  3. Vì chỉ các phương thức cá thể có thể được chế giễu, các lớp được kiểm tra đơn vị không thể gọi bất kỳ phương thức tĩnh nào trên các phụ thuộc của chúng, cũng không thể khởi tạo chúng bằng cách sử dụng bất kỳ hàm tạo nào.

Ở trên được sao chép từ http://jmockit.org/about.html . Hơn nữa, nó so sánh giữa chính nó (JMockit), PowerMock và Mockito theo nhiều cách:

Hiện tại có các công cụ giả định khác dành cho Java cũng khắc phục các hạn chế của các công cụ thông thường, giữa chúng là PowerMock, j EASTest và MockInject. Ứng dụng gần nhất với bộ tính năng của JMockit là PowerMock, vì vậy tôi sẽ đánh giá ngắn gọn về nó ở đây (bên cạnh đó, hai cái còn lại bị hạn chế hơn và dường như không được phát triển tích cực nữa).

JMockit vs PowerMock

  • Trước hết, PowerMock không cung cấp API hoàn chỉnh để chế nhạo mà thay vào đó hoạt động như một tiện ích mở rộng cho một công cụ khác, hiện có thể là EasyMock hoặc Mockito. Đây rõ ràng là một lợi thế cho người dùng hiện tại của những công cụ đó.
  • Mặt khác, JMockit cung cấp các API hoàn toàn mới, mặc dù API chính (Kỳ vọng) của nó tương tự như cả EasyMock và jMock. Mặc dù điều này tạo ra một đường cong học tập dài hơn, nó cũng cho phép JMockit cung cấp API đơn giản hơn, nhất quán hơn và dễ sử dụng hơn.
  • So với API kỳ vọng JMockit, API PowerMock "mức độ thấp" hơn, buộc người dùng phải tìm ra và chỉ định các lớp nào cần được chuẩn bị để thử nghiệm (với chú thích @PrepareForTest ({ClassA. Class, ...}) ) và yêu cầu các lệnh gọi API cụ thể để xử lý các loại cấu trúc ngôn ngữ khác nhau có thể có trong mã sản xuất: phương thức tĩnh (mockStatic (ClassA. class)), hàm tạo (triệt tiêu (hàm tạo (ClassXyz. class)), các lệnh xây dựng ( mong đợi New (AClass. class)), một phần giả (createdPartialMock (ClassX. class, "methodToMock")), v.v.
  • Với Kỳ vọng JMockit, tất cả các loại phương thức và hàm tạo được chế giễu theo cách khai báo thuần túy, với chế độ nhạo báng một phần được chỉ định thông qua các biểu thức chính quy trong chú thích @Mocked hoặc đơn giản là "không chế nhạo" các thành viên không có kỳ vọng được ghi lại; nghĩa là, nhà phát triển chỉ đơn giản khai báo một số "trường giả" được chia sẻ cho lớp thử nghiệm hoặc một số "trường giả lập cục bộ" và / hoặc "tham số giả" cho các phương thức thử nghiệm riêng lẻ (và trong trường hợp cuối cùng này, chú thích @Mocked thường không Cần thiết).
  • Một số khả năng có sẵn trong JMockit, chẳng hạn như hỗ trợ cho việc giả định bằng và hashCode, các phương thức được ghi đè và các phương thức khác, hiện không được hỗ trợ trong PowerMock. Ngoài ra, không có khả năng tương đương với khả năng của JMockit trong việc nắm bắt các thể hiện và giả định các kiểu cơ sở được chỉ định khi thực thi thử nghiệm, mà bản thân mã kiểm tra không có bất kỳ kiến ​​thức nào về các lớp triển khai thực tế.
  • PowerMock sử dụng các trình nạp lớp tùy chỉnh (thường là một cho mỗi lớp kiểm tra) để tạo các phiên bản sửa đổi của các lớp bị giả định. Việc sử dụng nhiều trình tải lớp tùy chỉnh như vậy có thể dẫn đến xung đột với các thư viện của bên thứ ba, do đó đôi khi cần phải sử dụng chú thích @PowerMockIgnore ("gói.to.be.ignored") trên các lớp kiểm tra.
  • Cơ chế được JMockit sử dụng (công cụ thời gian chạy thông qua "tác nhân Java") đơn giản và an toàn hơn, mặc dù nó yêu cầu chuyển tham số "-javaagent" cho JVM khi phát triển trên JDK 1.5; trên JDK 1.6+ (luôn có thể được sử dụng để phát triển, ngay cả khi triển khai trên phiên bản cũ hơn), không có yêu cầu nào như vậy, vì JMockit có thể tải rõ ràng tác nhân Java theo yêu cầu bằng cách sử dụng API đính kèm.

Một công cụ chế nhạo gần đây là Mockito. Mặc dù nó không cố gắng khắc phục những hạn chế của các công cụ cũ hơn (jMock, EasyMock), nhưng nó giới thiệu một phong cách thử nghiệm hành vi mới với giả. JMockit cũng hỗ trợ kiểu thay thế này, thông qua API Xác minh.

JMockit vs Mockito

  • Mockito dựa vào các cuộc gọi rõ ràng đến API của nó để phân tách mã giữa các bản ghi (khi (...)) và xác minh (xác minh (...)). Điều này có nghĩa là bất kỳ lời mời nào đến một đối tượng giả trong mã kiểm tra cũng sẽ yêu cầu một cuộc gọi đến API giả. Ngoài ra, điều này thường sẽ dẫn đến lặp đi lặp lại khi (...) và xác minh (giả) cuộc gọi.
  • Với JMockit, không có cuộc gọi tương tự tồn tại. Chắc chắn, chúng ta có các lệnh gọi hàm tạo NonStrictExpectations () và Verifying () mới, nhưng chúng chỉ xảy ra một lần cho mỗi thử nghiệm (thông thường) và tách biệt hoàn toàn với các phương thức và hàm tạo bị chế giễu.
  • API Mockito chứa một số điểm không nhất quán trong cú pháp được sử dụng cho các yêu cầu đối với các phương thức bị chế giễu. Trong giai đoạn ghi, chúng ta có các cuộc gọi như khi (mock.mockedMethod (args)) ... trong khi trong giai đoạn xác minh, cuộc gọi tương tự này sẽ được viết dưới dạng xác minh (mock) .mockedMethod (args). Lưu ý rằng trong trường hợp đầu tiên, việc gọi tới mockedMethod được thực hiện trực tiếp trên đối tượng giả, trong trường hợp thứ hai, nó được thực hiện trên đối tượng được trả về bằng cách xác minh (giả).
  • JMockit không có sự mâu thuẫn như vậy bởi vì các yêu cầu đối với các phương thức bị chế giễu luôn được thực hiện trực tiếp trên chính các trường hợp bị chế giễu. . )
  • Cũng giống như các công cụ chế nhạo khác dựa trên chuỗi / gói phương thức, Mockito cũng chạy theo cú pháp không nhất quán khi bỏ các phương thức void. Ví dụ: bạn viết khi (mockedList.get (1)). ThenThrow (new RuntimeException ()); cho một phương thức không trống và doThrow (new RuntimeException ()). khi (mockedList) .clear (); cho một khoảng trống Với JMockit, nó luôn có cùng một cú pháp: mockedList.clear (); result = new RuntimeException ();.
  • Tuy nhiên, một sự mâu thuẫn khác xảy ra trong việc sử dụng các điệp viên Mockito: "giả" cho phép các phương thức thực sự được thực thi trong trường hợp gián điệp. Ví dụ: nếu gián điệp đề cập đến một Danh sách trống, thì thay vì viết khi (spy.get (0)). ThenReturn ("foo"), bạn sẽ cần phải viết doReturn ("foo"). Khi (gián điệp) .get ( 0). Với JMockit, tính năng mô phỏng động cung cấp chức năng tương tự như gián điệp, nhưng không có vấn đề này vì các phương thức thực sự chỉ được thực thi trong giai đoạn phát lại.
  • Trong EasyMock và jMock, các API giả định đầu tiên cho Java, trọng tâm hoàn toàn tập trung vào việc ghi lại các yêu cầu dự kiến ​​của các phương thức giả, đối với các đối tượng giả định (theo mặc định) không cho phép các lệnh bất ngờ. Các API đó cũng cung cấp bản ghi các yêu cầu được phép cho các đối tượng giả cho phép các yêu cầu bất ngờ, nhưng điều này được coi là một tính năng hạng hai. Ngoài ra, với các công cụ này, không có cách nào để xác minh rõ ràng các yêu cầu đối với giả sau khi mã được kiểm tra được thực thi. Tất cả các xác minh như vậy được thực hiện ngầm và tự động.
  • Trong Mockito (và cả trong Unitils Mock), quan điểm ngược lại được thực hiện. Tất cả các yêu cầu để chế nhạo các đối tượng có thể xảy ra trong quá trình thử nghiệm, dù được ghi lại hay không, đều được cho phép, không bao giờ được mong đợi. Việc xác minh được thực hiện rõ ràng sau khi mã được kiểm tra được thực hiện, không bao giờ tự động.
  • Cả hai cách tiếp cận đều quá cực đoan, và do đó ít hơn tối ưu. JMockit Expectations & Verifying là API duy nhất cho phép nhà phát triển lựa chọn liền mạch sự kết hợp tốt nhất giữa các yêu cầu giả định nghiêm ngặt (theo mặc định) và không nghiêm ngặt (theo mặc định) cho mỗi thử nghiệm.
  • Để rõ ràng hơn, API Mockito có những thiếu sót sau đây. Nếu bạn cần xác minh rằng một lệnh gọi đến phương thức giả không trống đã xảy ra trong quá trình thử nghiệm, nhưng thử nghiệm yêu cầu giá trị trả về từ phương thức đó khác với mặc định cho loại trả về, thì thử nghiệm Mockito sẽ có mã trùng lặp: a khi (mock.someMethod ()). thenReturn (xyz) gọi trong pha ghi và xác minh (mock) .someMethod () trong pha xác minh. Với JMockit, một kỳ vọng nghiêm ngặt luôn có thể được ghi lại, điều này sẽ không phải được xác minh rõ ràng. Ngoài ra, một ràng buộc số lần gọi (lần = 1) có thể được chỉ định cho bất kỳ kỳ vọng không nghiêm ngặt nào được ghi lại (với Mockito, các ràng buộc đó chỉ có thể được chỉ định trong lệnh gọi xác minh (giả định, ràng buộc)).
  • Mockito có cú pháp kém để xác minh theo thứ tự và để xác minh đầy đủ (nghĩa là kiểm tra xem tất cả các yêu cầu đối với các đối tượng giả được xác minh rõ ràng). Trong trường hợp đầu tiên, một đối tượng bổ sung cần được tạo và gọi để xác minh được thực hiện trên nó: InOrder inOrder = inOrder (mock1, mock2, ...). Trong trường hợp thứ hai, các cuộc gọi như verifyNoMoreInterilities (mock) hoặc verifyZeroInterilities (mock1, mock2) cần được thực hiện.
  • Với JMockit, bạn chỉ cần viết VerifyingInOrder () hoặc FullVerifying mới () thay vì Verifying mới () (hoặc FullVerifyingInOrder () mới để kết hợp cả hai yêu cầu). Không cần chỉ định những đối tượng giả có liên quan. Không có cuộc gọi API chế giễu thêm. Và như một phần thưởng, bằng cách gọi unverifiedInvocations () bên trong một khối xác minh được đặt hàng, bạn có thể thực hiện các xác minh liên quan đến đơn hàng mà đơn giản là không thể có trong Mockito.

Cuối cùng, Bộ công cụ kiểm tra JMockit có phạm vi rộng hơncác mục tiêu đầy tham vọng hơn các bộ công cụ chế giễu khác, để cung cấp một giải pháp kiểm tra dành cho nhà phát triển hoàn chỉnh và tinh vi. Một API tốt để chế nhạo, ngay cả khi không có giới hạn nhân tạo, là không đủ để tạo ra các thử nghiệm hiệu quả. Một công cụ không bao gồm IDE, dễ sử dụng và được tích hợp tốt cũng là điều cần thiết và đó là điều mà JMockit Co hiểm hướng đến. Một phần khác của bộ công cụ kiểm tra dành cho nhà phát triển sẽ trở nên hữu ích hơn khi bộ kiểm thử tăng kích thước là khả năng chạy lại các bài kiểm tra sau khi thay đổi cục bộ thành mã sản xuất; điều này cũng được bao gồm trong công cụ Bảo hiểm.

(được cấp, nguồn có thể bị sai lệch, nhưng cũng ...)

Tôi muốn nói đi với JMockit . Đây là cách dễ sử dụng, linh hoạt và hoạt động nhất đối với hầu hết các trường hợp ngay cả những trường hợp và tình huống khó khăn khi bạn không thể kiểm soát lớp được kiểm tra (hoặc bạn không thể phá vỡ nó vì lý do tương thích, v.v.).

Những trải nghiệm của tôi với JMockit đã rất tích cực.


1
Tôi chưa bao giờ sử dụng jmockit, nhưng tôi muốn thêm một đối số khác vào cuộc thảo luận: hãy xem so sánh xu hướng của google về tất cả các khung thảo luận. Kể từ ngày 06/06/2012, JMockit thậm chí không hiển thị trên biểu đồ xu hướng của google khi so sánh với Mockito và EasyMock. Và số lượng người dùng cũng rất quan trọng khi chọn một khung.
máy móc

3
Điều đó khá lạ. Mockito và JMockIt cho tôi lượt truy cập tương ứng 409 'và 83' trên google. Chắc chắn JMockIt sẽ xuất hiện ít nhất.
thoredge

5
Câu trả lời của bạn rất hữu ích. Tôi đã lên kế hoạch đơn giản là sử dụng Mockito, nhưng bây giờ tôi sẽ kiểm tra JMockit trước. Nghe có vẻ tốt để không thử nó. @machowder: Vâng, điều quan trọng là phải xem xét các xu hướng, nhưng chọn nó làm tiêu chí chính sẽ hạn chế bạn vào luồng chính và bảo vệ bạn khỏi sự đổi mới.
deamon

1
Tôi biết đây là một chủ đề cũ, nhưng sau khi đọc bài đánh giá này, tôi nghĩ rằng tôi cũng sẽ cho nó một shot. Tôi phải nói rằng, nhìn bề ngoài, JMockit rất hứa hẹn. Tuy nhiên, cho đến nay, tôi đã tìm thấy sự hỗ trợ cộng đồng cho nó rất thiếu. Tôi đang gặp vấn đề lớn với sự hiểu biết của mình về API Mock và sau khi đăng các vấn đề của mình, tôi đã không có phản hồi trong 2 ngày.
Eric B.

1
Câu trả lời là 8 tuổi, rất nhiều điều trong câu trả lời không còn đúng nữa. Một điểm là JMockit yêu cầu -javaagentcờ từ 1.42 vì bạn không thể tự đính kèm nữa kể từ Java 9 và việc tìm kiếm các công việc phù hợp rõ ràng không nằm trong phạm vi của nhà phát triển. Một điểm khác là JMockit không cho phép chế nhạo các phương thức và hàm tạo riêng tư trong khi PowerMock thực hiện.
Ma cà rồng

24

Tôi đã làm việc với cả Mockito và JMockit, và kinh nghiệm của tôi với họ là:

  • Mockito:

    • chế nhạo ngầm (-> khả năng sử dụng tốt hơn, nhưng có nguy cơ không phát hiện ra các cuộc gọi phương thức không được phép trên giả)
    • xác minh rõ ràng
  • EasyMock:

    • chế nhạo
    • xác minh ngầm
  • JMockit:

    • hỗ trợ cả
  • Bên cạnh đó, những lợi ích khác của JMockit:

    • nếu bạn đang chế giễu các phương thức / hàm tạo tĩnh, v.v. (chẳng hạn như mở rộng cơ sở mã kế thừa rất cũ mà không có UT), bạn sẽ có hai lựa chọn: 1) Mockito / EasyMock với tiện ích mở rộng Powermock hoặc 2) Jmockit
    • báo cáo bảo hiểm tích hợp

Cá nhân tôi thích JMockit, mà tôi nghĩ là nhiều tính năng phong phú và linh hoạt hơn, nhưng đòi hỏi một chút đường cong học tập dốc hơn một chút. Thường có nhiều cách để đạt được hiệu ứng nhạo báng giống nhau và đòi hỏi nhiều sự cẩn thận hơn khi thiết kế các bản giả.


stackoverflow.com/questions/8003278/ hy "verifyNoMoreInterilities" Tôi cho rằng nếu bạn muốn giả mạo rõ ràng giả với mockito
rogerdpack

15

Tôi sử dụng jMockit chỉ vì nó phản ánh các thư viện trong Deencapsultation.class. Tôi thực sự yêu thích phong cách của Mockito, nhưng tôi từ chối thay đổi mã của mình và làm rối tung API của tôi chỉ để một khung kiểm tra giới hạn có thể có được. Và tôi là người thích thử nghiệm tất cả mã của mình, vì vậy một khung không thể dễ dàng kiểm tra các phương thức riêng tư không phải là thứ tôi muốn sử dụng.

Tôi đã bị ảnh hưởng bởi bài viết này

Sau một quá trình học tập (thừa nhận lớn), jMockit hiện là khung thử nghiệm đơn vị chính của tôi cho các giả.


7
Có lẽ nếu bạn cảm thấy cần phải kiểm tra các phương thức riêng tư, bạn quá quan tâm đến cách mã của bạn hoạt động, hơn là với những gì nó làm (đó là điểm thực và có thể được xác định bằng cách chỉ thực hiện các phương thức công khai của nó). Ngoài ra, tôi sẽ quan tâm để đọc bài viết đó, nhưng liên kết bị hỏng.
codebox

4 năm sau, bạn vẫn đang sử dụng jMockit làm khung thử nghiệm chính của mình chứ? Tôi đang dùng thử lần đầu tiên và gặp một số vấn đề với nó nhưng tôi không biết liệu tôi có hiểu nhầm cách jMockit hoạt động hay không, nếu đó là một tính năng không tồn tại.
Eric B.

jMockit không còn hỗ trợ thử nghiệm các phương thức riêng tư. Lớp Deencapsulation dần bị phản đối và sau đó bị loại bỏ hoàn toàn trong phiên bản 1.47. jmockit.github.io/changes.html
Pytry

4

Để dễ dàng kiểm tra cơ sở mã di sản của chúng tôi (với rất nhiều lệnh gọi phương thức tĩnh, v.v.), JMockit là vô giá. [Cắm không biết xấu hổ cho một bài viết trên blog của tôi]


0

Cá nhân tôi thích EasyMock .
Khả năng chuyển hướng giữa các điều khiển chế giễu đẹp, bình thường và nghiêm ngặt là một trong những tính năng yêu thích của tôi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.