programing

Mockito와 JMockit의 비교 - 왜 Mockito가 JMockit보다 투표가 더 좋은가?

projobs 2022. 10. 1. 14:23
반응형

Mockito와 JMockit의 비교 - 왜 Mockito가 JMockit보다 투표가 더 좋은가?

프로젝트에 어떤 모킹 프레임워크를 사용할지 조사하고 있으며, JMockitMockito로 좁혔습니다.

Mockito는 Stackoverflow에서 "Java를 위한 최고의 모의 프레임워크"선정되었습니다.
JMockit의 "Mocking Tool Comparision Matrix" 기능을 비교하면 JMockit에는 여러 가지 다른 기능이 있는 것으로 보입니다.

JMockit에서는 달성할 수 없는 Mockito의 기능에 대한 구체적인 정보(의견 없음)를 가지고 있는 사람이 있습니까?

2019년 9월 갱신:Spring Boot에서 지원되는 유일한 모의 프레임워크Mockito입니다.만약 당신이 봄을 사용한다면, 답은 매우 명백하다.


JMockitPowerMock, 그리고 Mockito의 대결이라고 생각합니다.

jMock과 EasyMock은 프록시 및 CGLIB만을 사용하고 새로운 프레임워크와 같은 Java 5 instrumentation은 사용하지 않기 때문에 그대로 두겠습니다.

jMock도 4년 이상 안정된 릴리스가 없었습니다.jMock 2.6.0은 RC1에서 RC2로 이행하는 데 2년이 걸렸고, 그 후 실제로 출시되기까지 2년이 더 걸렸습니다.

Proxy & CGLIB vs instrumentation에 대해서:

(EasyMock 및 jMock)은 java.lang.reflect를 기반으로 합니다.프록시: 실장할 인터페이스가 필요합니다.또한 CGLIB 서브클래스 생성을 통한 클래스용 모의 객체 생성을 지원합니다.따라서 해당 클래스는 최종 클래스가 될 수 없으며 덮어쓸 수 있는 인스턴스 메서드만 조롱할 수 있습니다.단, 이들 툴을 사용할 때 가장 중요한 것은 테스트 대상 코드의 의존성(즉 테스트 대상 클래스가 의존하는 다른 클래스의 오브젝트)이 테스트에 의해 제어되어야 하며, 따라서 이러한 의존성의 클라이언트에 모의 인스턴스가 전달될 수 있습니다.따라서 유닛테스트를 작성하는 클라이언트클래스의 새로운 연산자에서는 의존관계를 단순히 인스턴스화할 수 없습니다.

궁극적으로, 기존의 조롱 도구의 기술적 제한으로 인해 생산 코드에 다음과 같은 설계 제한이 부과됩니다.

  1. 테스트에서 조롱할 필요가 있는 각 클래스는 별도의 인터페이스를 구현하거나 최종 인터페이스가 아니어야 합니다.
  2. 테스트할 각 클래스의 의존성은 설정 가능한 인스턴스 작성 방식(팩토리 또는 서비스 로케이터)을 통해 취득하거나 의존성 주입을 위해 공개해야 합니다.그렇지 않으면 장치 테스트가 종속성의 모의 구현을 테스트 대상 장치에 전달할 수 없습니다.
  3. 인스턴스 메서드만 조롱할 수 있으므로 유닛 테스트 대상 클래스는 종속성에 대한 정적 메서드를 호출할 수 없으며 생성자를 사용하여 인스턴스화할 수도 없습니다.

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

PowerMock, jEasy 등 기존 툴의 한계를 극복한 자바용 모킹 툴도 있습니다.테스트 및 Mock Inject.JMockit의 기능 세트에 가장 가까운 것은 PowerMock이기 때문에 여기서 간단하게 평가하겠습니다(게다가 나머지 2개는 한정되어 있어 현재 개발이 활발하지 않은 것 같습니다).

JMockit vs PowerMock

  • 우선 PowerMock은 모킹용 API를 완전히 제공하는 것이 아니라 현재 EasyMock 또는 Mockito일 수 있는 다른 툴의 확장으로 기능합니다.이는 이러한 툴의 기존 사용자에게 명백한 이점입니다.
  • 반면 JMockit은 완전히 새로운 API를 제공하지만 메인 API(Expections)는 EasyMock과 jMock 모두와 유사합니다.이것에 의해, 보다 긴 학습 곡선이 작성되는 한편, JMockit는 보다 심플하고 일관성이 있어 사용하기 쉬운 API를 제공할 수 있습니다.
  • JMockit Expections API에 비해 PowerMock API는 "로우 레벨"이기 때문에 사용자는 테스트를 위해 준비해야 할 클래스를 파악하고 지정해야 합니다(@PrepareForTest({ClassA.class, ...).( ) 주석) 및 프로덕션 코드에 존재할 수 있는 다양한 종류의 언어 구성 요소를 처리하기 위해 특정 API 호출이 필요합니다. 정적 메서드(mockStatic(ClassA.class), 컨스트럭터(suppress(constructor(ClassXz.class)), 컨스트럭터 호출(expectNew(ACLASClass)), 부분 mocks(PartialMocksCreateMock)입니다.( ) 등).
  • JMockit Expections에서는 모든 종류의 메서드와 컨스트럭터가 순전히 선언적인 방법으로 조롱됩니다.@Mocked 주석의 정규 표현을 통해 지정되거나 단순히 기록된 기대 없이 멤버를 "Mocking 해제"함으로써, 즉 개발자는 테스트 클래스에 대해 공유된 "mock 필드"를 선언합니다.e 개별 테스트 방법에 대한 "로컬 모의 필드" 및/또는 "모크 매개 변수" (그리고 이 마지막 경우 @Mocked 주석은 종종 필요하지 않습니다)
  • JMockit에서 사용할 수 있는 일부 기능(예: mocking equals 및 hashCode 지원, 재정의된 메서드 등)은 현재 PowerMock에서 지원되지 않습니다.또한 테스트 코드 자체에 실제 구현 클래스에 대한 지식이 없어도 테스트 실행 시 지정된 기본 유형의 인스턴스 및 모의 구현을 캡처하는 JMockit의 기능과 동등한 기능은 없습니다.
  • PowerMock은 커스텀클래스 로더(일반적으로 테스트클래스당 1개)를 사용하여 조롱된 클래스의 수정 버전을 생성합니다.커스텀 클래스 로더를 이렇게 많이 사용하면 서드파티 라이브러리와 경합할 수 있습니다.따라서 테스트클래스에서 @PowerMockIgnore("package.to.be.Ignored") 주석을 사용할 필요가 있습니다.
  • JMockit('Java 에이전트'를 통한 런타임 인스트루먼테이션)이 사용하는 메커니즘은 더 간단하고 안전하지만 JDK 1.5에서 개발할 때 "-javaagent" 매개 변수를 JVM에 전달해야 합니다. JDK 1.6+에서는 JM을 도입할 필요가 없기 때문에 JDK 1.6+에서 항상 개발에 사용할 수 있습니다.tly API를 사용하여 Java 에이전트를 온디맨드로 로드합니다.

최근의 또 다른 조롱 도구는 모키토입니다.오래된 도구(jMock, EasyMock)의 한계를 극복하려는 것은 아니지만, 모크를 사용한 새로운 스타일의 동작 테스트를 도입하고 있습니다.또한 JMockit은 검증 API를 통해 이 대체 스타일을 지원합니다.

JMockit vs Mockito

  • Mockito는 레코드(시기(...) 단계와 검증(...) 단계 간에 코드를 분리하기 위해 API에 대한 명시적 호출에 의존합니다.즉, 테스트 코드의 모의 객체에 대한 호출은 모의 API 호출도 필요합니다.또한 (...)와 verify(mock)를 반복하는 경우가 많습니다.콜을 클릭합니다.
  • JMockit에서는 유사한 콜은 존재하지 않습니다.물론 새로운 NonStrictExpections() 및 새로운 Verifications() 컨스트럭터 호출이 있지만 테스트당 1회(일반적으로)만 발생하며 조롱된 메서드 및 컨스트럭터에 대한 호출과는 완전히 분리되어 있습니다.
  • Mockito API에는 조롱된 메서드에 대한 호출에 사용되는 구문에 몇 가지 불일치가 있습니다.레코드 단계에서는 (mock.mockedMethod(args))와 같은 콜이 있습니다.검증 단계에서는 이 같은 콜이 verify(verify)로 써집니다.disced Methods(args)첫 번째 경우 mock 객체에 대해 discuredMethod 호출이 직접 이루어지는 반면 두 번째 경우 verify(mock)에 의해 반환된 객체에 대해 호출이 이루어집니다.
  • JMockit에는 이러한 불일치가 없습니다.이는 조롱된 메서드에 대한 호출이 항상 조롱된 인스턴스 자체에서 직접 이루어지기 때문입니다(단, 한 가지 예외는 같은 조롱된 인스턴스에서 호출을 일치시키기 위해 onInstance(mock) 콜이 사용되며 결과적으로 onInstance(mock)와 같은 코드가 생성됩니다.discured Methods(args). 단, 대부분의 테스트에서는 이 방법을 사용할 필요가 없습니다.
  • 메서드 체인/랩핑에 의존하는 다른 모킹툴과 마찬가지로 Mockito도 보이드 메서드를 스터핑할 때 일관성이 없는 구문에 부딪힙니다.예를 들어 when(mockedList.get(1)을 입력합니다.그러면 Throw(새로운 런타임)예외(); 비회피 메서드의 경우 및 doThrow(새로운 런타임)예외()).when(mocked List).clear(); void의 경우.JMockit에서는 항상 동일한 구문입니다. discuredList.clear(); result = new Runtime예외();
  • 그러나 Mockito 스파이 사용 시 또 다른 불일치가 발생합니다. 즉, 스파이 인스턴스에서 실제 메서드를 실행할 수 있는 "mocks"입니다.예를 들어 spy가 빈 목록을 참조하는 경우 spy.get(0).Return("foo")을 쓰는 대신 doReturn("foo")을 써야 합니다.언제(가)?)get(0). JMockit을 사용하면 다이내믹모킹 기능은 spy와 같은 기능을 제공하지만 실제 메서드는 재생 단계에서만 실행되므로 이 문제는 없습니다.
  • Java용 최초의 모의 API인 EasyMock과 jMock에서는 (기본적으로) 예기치 않은 호출을 허용하지 않는 모의 객체에 대해 모의 메서드의 예상 호출을 기록하는 데 초점을 맞췄다.이러한 API는 예기치 않은 호출을 허용하는 모의 객체에 대해 허용되는 호출 기록도 제공하지만 이는 2등급 기능으로 취급되었습니다.또한 이러한 툴을 사용하여 테스트 대상 코드를 실행한 후 모크에 대한 호출을 명시적으로 확인할 수 없습니다.이러한 검증은 모두 암묵적으로 자동으로 실행됩니다.
  • 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.

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

반응형