programing tip

Mockito와 JMockit의 비교-Mockito가 JMockit보다 더 나은 투표를하는 이유는 무엇입니까?

itbloger 2020. 7. 14. 19:19
반응형

Mockito와 JMockit의 비교-Mockito가 JMockit보다 더 나은 투표를하는 이유는 무엇입니까? [닫은]


내 프로젝트에 사용할 조롱 프레임 워크를 조사 중이며 JMockitMockito 로 축소했습니다 .

것을 나는 통지 Mockito가 있었다 "는 투표 자바에 가장 적합한 모의 프레임 워크를 유래에". JMockit 의 " Mocking Tool Comparision Matrix "
기능을 비교할 JMockit 에는 여러 가지 기능이있는 것으로 보입니다 .

사람이 무엇에 대한 특정 정보 (하지의 의견)이 있습니까 Mockito는 달성 할 수없는 할 수 JMockit 반대 및 부사장을?


2019 년 9 월 업데이트 : Spring Boot에서 기본적으로 지원하는 유일한 조롱 프레임 워크Mockito 입니다. Spring을 사용하면 답이 분명합니다.


나는 경쟁이 JMockitPowerMock , 그리고 Mockito 사이에 있다고 말합니다 .

프록시와 CGLIB 만 사용하고 최신 프레임 워크와 같은 Java 5 계측을 사용하지 않기 때문에 "일반"jMock과 EasyMock을 그대로 둡니다.

jMock은 또한 4 년 이상 안정적인 릴리스를 제공하지 않았습니다. jMock 2.6.0은 RC1에서 RC2로 이동하는 데 2 ​​년이 필요했으며 실제로 2 년이 지나야 실제로 릴리스되었습니다.

프록시 및 CGLIB 및 계측 관련 :

(EasyMock 및 jMock)은 java.lang.reflect.Proxy를 기반으로하며 인터페이스를 구현해야합니다. 또한 CGLIB 서브 클래스 생성을 통해 클래스 용 모의 오브젝트 작성을 지원합니다. 이로 인해, 상기 클래스는 최종 클래스가 될 수 없으며 재정의 가능한 인스턴스 메소드 만 조롱 할 수 있습니다. 그러나 가장 중요한 것은 이러한 도구를 사용할 때 테스트중인 코드의 종속성 (즉, 테스트중인 특정 클래스가 종속 된 다른 클래스의 오브젝트)이 테스트에 의해 제어되어야하므로 모의 인스턴스가 클라이언트에 전달 될 수 있습니다. 그 의존성의. 따라서 단위 테스트를 작성하려는 클라이언트 클래스에서 새 연산자로 종속성을 인스턴스화 할 수 없습니다.

궁극적으로 기존의 조롱 도구의 기술적 한계는 생산 코드에 다음과 같은 설계 제한을 부과합니다.

  1. 테스트에서 조롱해야 할 각 클래스는 별도의 인터페이스를 구현하거나 최종적이지 않아야합니다.
  2. 테스트 할 각 클래스의 종속성은 구성 가능한 인스턴스 생성 방법 (공장 또는 서비스 로케이터)을 통해 얻거나 종속성 주입에 노출되어야합니다. 그렇지 않으면, 유닛 테스트는 모의 의존성 구현을 테스트중인 유닛으로 전달할 수 없습니다.
  3. 인스턴스 메소드 만 조롱 할 수 있기 때문에 단위 테스트 할 클래스는 종속성에 대한 정적 메소드를 호출하거나 생성자를 사용하여 인스턴스화 할 수 없습니다.

위 내용은 http://jmockit.org/about.html 에서 복사되었습니다 . 또한 여러 가지 방법으로 자체 (JMockit), PowerMock 및 Mockito를 비교합니다.

이제 PowerMock, jEasyTest 및 MockInject 사이의 기존 도구의 한계를 극복하는 Java 용 다른 조롱 도구가 있습니다. JMockit의 기능 세트에 가장 가까운 것은 PowerMock이므로 여기서 간단히 평가할 것입니다 (단, 다른 두 가지는 더 제한적이며 더 이상 적극적으로 개발되지 않는 것 같습니다).

JMockit 및 PowerMock

  • 우선, PowerMock은 조롱을위한 완벽한 API를 제공하지 않고 현재 EasyMock 또는 Mockito 일 수있는 다른 도구의 확장으로 작동합니다. 이는 해당 도구를 사용하는 기존 사용자에게 유리합니다.
  • 반면 JMockit은 기본 API (예상)가 EasyMock 및 jMock과 유사하지만 완전히 새로운 API를 제공합니다. 학습 시간이 길어 지지만 JMockit은 더 단순하고 일관성 있고 사용하기 쉬운 API를 제공 할 수 있습니다.
  • JMockit Expectations API와 비교하여 PowerMock API는 "저수준"으로, 사용자가 테스트를 위해 준비 할 클래스를 파악하고 지정하도록합니다 (@PrepareForTest ({ClassA.class, ...}) 주석 사용) ) 및 프로덕션 코드에 존재할 수있는 다양한 종류의 언어 구성을 처리하기 위해 특정 API 호출이 필요합니다. 정적 메소드 (mockStatic (ClassA.class)), 생성자 (suppress (constructor (ClassXyz.class))), 생성자 호출 ( expectNew (AClass.class)), 부분 모의 (createPartialMock (ClassX.class, "methodToMock")) 등
  • JMockit Expectations를 사용하면 모든 종류의 메소드와 생성자가 순수하게 선언적인 방식으로 조롱되며 @Mocked 주석의 정규 표현식을 통해 또는 부분적으로 조롱이 기록되거나 예상치가 기록되지 않은 멤버를 단순히 "모의 조롱하지 않음"으로 선언됩니다. 즉, 개발자는 단순히 테스트 클래스에 대한 일부 공유 "모의 필드"또는 개별 테스트 방법에 대한 "로컬 모의 필드"및 / 또는 "모의 매개 변수"를 선언합니다 (이 경우 @Mocked 주석은 종종 필요합니다).
  • JMockit에서 사용 가능한 일부 기능 (예 : mocking equals 및 hashCode 지원, 재정의 된 메소드 등)은 현재 PowerMock에서 지원되지 않습니다. 또한 테스트 코드 자체에 실제 구현 클래스에 대한 지식이 없으면 테스트가 실행될 때 지정된 기본 유형의 인스턴스를 캡처하고 구현하는 JMockit의 기능과 동등한 기능이 없습니다.
  • PowerMock은 모의 클래스의 수정 된 버전을 생성하기 위해 사용자 정의 클래스 로더 (일반적으로 테스트 클래스 당 하나)를 사용합니다. 사용자 정의 클래스 로더를 과도하게 사용하면 써드 파티 라이브러리와 충돌 할 수 있으므로 테스트 클래스에서 @PowerMockIgnore ( "package.to.be.ignored") 주석을 사용해야하는 경우가 있습니다.
  • The mechanism used by JMockit (runtime instrumentation through a "Java agent") is simpler and safer, although it does require passing a "-javaagent" parameter to the JVM when developing on JDK 1.5; on JDK 1.6+ (which can always be used for development, even if deploying on an older version) there is no such requirement, since JMockit can transparently load the Java agent on demand by using the Attach API.

Another recent mocking tool is Mockito. Although it does not attempt to overcome the limitations of older tools (jMock, EasyMock), it does introduce a new style of behavior testing with mocks. JMockit also supports this alternative style, through the Verifications API.

JMockit vs Mockito

  • Mockito relies on explicit calls to its API in order to separate code between the record (when(...)) and verify (verify(...)) phases. This means that any invocation to a mock object in test code will also require a call to the mocking API. Additionally, this will often lead to repetitive when(...) and verify(mock)... calls.
  • With JMockit, no similar calls exist. Sure, we have the new NonStrictExpectations() and new Verifications() constructor calls, but they occur only once per test (typically), and are completely separate from the invocations to mocked methods and constructors.
  • The Mockito API contains several inconsistencies in the syntax used for invocations to mocked methods. In the record phase, we have calls like when(mock.mockedMethod(args))... while in the verify phase this same call will be written as verify(mock).mockedMethod(args). Notice that in the first case the invocation to mockedMethod is made directly on the mock object, while in the second case it is made on the object returned by verify(mock).
  • JMockit has no such inconsistencies because invocations to mocked methods are always made directly on the mocked instances themselves. (With one exception only: to match invocations on the same mocked instance, an onInstance(mock) call is used, resulting in code like onInstance(mock).mockedMethod(args); most tests won't need to use this, though.)
  • Just like other mocking tools which rely on method chaining/wrapping, Mockito also runs into inconsistent syntax when stubbing void methods. For example, you write when(mockedList.get(1)).thenThrow(new RuntimeException()); for a non-void method, and doThrow(new RuntimeException()).when(mockedList).clear(); for a void one. With JMockit, it's always the same syntax: mockedList.clear(); result = new RuntimeException();.
  • Yet another inconsistency occurs in the use of Mockito spies: "mocks" that allow the real methods to be executed on the spied instance. For example, if spy refers to an empty List, then instead of writing when(spy.get(0)).thenReturn("foo") you will need to write doReturn("foo").when(spy).get(0). With JMockit, the dynamic mocking feature provides similar functionality to spies, but without this issue since real methods only get executed during the replay phase.
  • In EasyMock and jMock, the first mocking APIs for Java, the focus was entirely on the recording of expected invocations of mocked methods, for mock objects that (by default) do not allow unexpected invocations. Those APIs also provide the recording of allowed invocations for mock objects that do allow unexpected invocations, but this was treated as a second-class feature. Additionally, with these tools there is no way to explicitly verify invocations to mocks after the code under test is exercised. All such verifications are performed implicitly and automatically.
  • In Mockito (and also in Unitils Mock), the opposite viewpoint is taken. All invocations to mock objects that may happen during the test, whether recorded or not, are allowed, never expected. Verification is performed explicitly after the code under test is exercised, never automatically.
  • Both approaches are too extreme, and consequently less than optimal. JMockit Expectations & Verifications is the only API that allows the developer to seamlessly choose the best combination of strict (expected by default) and non-strict (allowed by default) mock invocations for each test.
  • To be more clear, the Mockito API has the following shortcoming. If you need to verify that an invocation to a non-void mocked method happened during the test, but the test requires a return value from that method that is different from the default for the return type, then the Mockito test will have duplicate code: a when(mock.someMethod()).thenReturn(xyz) call in the record phase, and a verify(mock).someMethod() in the verify phase. With JMockit, a strict expectation can always be recorded, which won't have to be explicitly verified. Alternatively, an invocation count constraint (times = 1) can be specified for any recorded non-strict expectation (with Mockito such constraints can only be specified in a verify(mock, constraint) call).
  • Mockito has poor syntax for verifications in order, and for full verifications (that is, checking that all invocations to mock objects are explicitly verified). In the first case, an extra object needs to be created, and calls to verify made on it: InOrder inOrder = inOrder(mock1, mock2, ...). In the second case, calls like verifyNoMoreInteractions(mock) or verifyZeroInteractions(mock1, mock2) need to be made.
  • With JMockit, you simply write new VerificationsInOrder() or new FullVerifications() instead of new Verifications() (or new FullVerificationsInOrder() to combine both requirements). No need to specify which mock objects are involved. No extra mocking API calls. And as a bonus, by calling unverifiedInvocations() inside an ordered verification block, you can perform order-related verifications that are simply impossible in Mockito.

Finally, the JMockit Testing Toolkit has a wider scope and more ambitious goals than other mocking toolkits, in order to provide a complete and sophisticated developer testing solution. A good API for mocking, even without artificial limitations, is not enough for productive creation of tests. An IDE-agnostic, easy to use, and well integrated Code Coverage tool is also essential, and that's what JMockit Coverage aims to provide. Another piece of the developer testing toolset which will become more useful as the test suite grows in size is the ability to incrementally rerun tests after a localized change to production code; this is also included in the Coverage tool.

(granted, the source may be biased, but well...)

I'd say go with JMockit. It's the easiest to use, flexible, and works for pretty much all cases even difficult ones and scenarios when you can't control the class to be tested (or you can't break it due to compatibility reasons etc.).

My experiences with JMockit have been very positive.


I worked with both Mockito and JMockit, and my experience with them is:

  • Mockito:

    • implicit mocking (-> better usability, but has the danger of failing to detect not-allowed method calls on mocks)
    • explicit verification
  • EasyMock:

    • explict mocking
    • implicit verification
  • JMockit:

    • supports both
  • Besides, other benefits of JMockit:

    • if you're mocking static methods/constructors etc (such as extending a very old legacy code base without UT), you'll have two choices: 1) Mockito/EasyMock with Powermock extension or 2) Jmockit
    • built-in coverage report

I personally prefer JMockit, which I think is more feature rich and flexible, but requires a little bit steeper learning curve. There're usually multiple ways to achieve the same mocking effect, and requires more care when designing the mocks.


I use jMockit only because of it's reflection libraries in Deencapsultation.class. I actually love Mockito's style, but I refuse to change my code and muddy up my API just so a limited testing framework can get at it. And I'm a fan of testing all my code, so a framework that can't easily test private methods is not what I want to be using.

I was swayed by this article

After a (admittedly large) learning curve, jMockit is now my main unit testing framework for mocks.


For easy testing of our legacy codebase (with lots of static method calls, etc.), JMockit has been invaluable. [Shameless plug for an article on my blog]


I personally prefer EasyMock.
The ability to divert between nice, normal and strict mocking controls is one on my favorite feature.

참고URL : https://stackoverflow.com/questions/4105592/comparison-between-mockito-vs-jmockit-why-is-mockito-voted-better-than-jmockit

반응형