[java] mockito로 최종 수업을 조롱하는 방법
나는 마지막 수업을 가지고 있습니다 :
public final class RainOnTrees{
public void startRain(){
// some code here
}
}
이 클래스를 다음과 같은 다른 클래스에서 사용하고 있습니다.
public class Seasons{
RainOnTrees rain = new RainOnTrees();
public void findSeasonAndRain(){
rain.startRain();
}
}
JUnit 테스트 클래스 Seasons.java
에서 RainOnTrees
클래스 를 조롱하고 싶습니다 . Mockito로 어떻게 할 수 있습니까?
답변
최종 / 정적 클래스 / 메소드를 조롱하는 것은 Mockito v2에서만 가능합니다.
gradle 파일에 이것을 추가하십시오 :
testImplementation 'org.mockito:mockito-inline:2.13.0'
Mockito FAQ 의 Mockito v1에서는 불가능합니다 .
Mockito의 한계는 무엇입니까
Java 1.5 이상이 필요합니다
최종 수업을 조롱 할 수 없습니다
…
답변
Mockito 2는 이제 최종 클래스와 메소드를 지원 합니다!
그러나 현재로서는 “인큐베이팅”기능입니다. Mockito 2의 새로운 기능에 설명 된대로 활성화하려면 몇 가지 단계가 필요합니다 .
최종 클래스와 메서드를 조롱하는 것은 잠복 하고 옵트 인 기능입니다. Java 에이전트 인스 트루먼 테이션과 서브 클래 싱의 조합을 사용하여 이러한 유형의 모형을 구현할 수 있습니다. 이 기능은 현재 메커니즘과 다르게 작동하며 다른 제한 사항이 있으며 경험과 사용자 피드백을 수집하려면이 기능을 명시 적으로 활성화해야 사용할 수 있습니다.
src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
단일 행을 포함하는 파일을 작성하여 mockito 확장 메커니즘을 통해 수행 할 수 있습니다 .mock-maker-inline
이 파일을 만든 후 Mockito는이 새 엔진을 자동으로 사용하며 다음을 수행 할 수 있습니다.
final class FinalClass { final String finalMethod() { return "something"; } } FinalClass concrete = new FinalClass(); FinalClass mock = mock(FinalClass.class); given(mock.finalMethod()).willReturn("not anymore"); assertThat(mock.finalMethod()).isNotEqualTo(concrete.finalMethod());
이후 이정표에서 팀은이 기능을 사용하는 프로그래밍 방식을 제공합니다. 우리는 모든 불가능한 시나리오를 식별하고 지원할 것입니다. 지켜봐 주시고이 기능에 대한 귀하의 의견을 알려주십시오!
답변
혼자서 할 수 없으므로 Mockito로 최종 수업을 조롱 할 수 없습니다.
내가하는 일은 최종 클래스를 포장하고 대리자로 사용하기 위해 최종 클래스가 아닌 클래스를 만드는 것입니다. 이것의 예는 TwitterFactory
클래스이며, 이것은 내 조롱 가능한 클래스입니다.
public class TwitterFactory {
private final twitter4j.TwitterFactory factory;
public TwitterFactory() {
factory = new twitter4j.TwitterFactory();
}
public Twitter getInstance(User user) {
return factory.getInstance(accessToken(user));
}
private AccessToken accessToken(User user) {
return new AccessToken(user.getAccessToken(), user.getAccessTokenSecret());
}
public Twitter getInstance() {
return factory.getInstance();
}
}
단점은 많은 상용구 코드가 있다는 것입니다. 장점은 애플리케이션 비즈니스와 관련된 몇 가지 메소드를 추가 할 수 있다는 것입니다 (위의 경우 accessToken 대신 사용자를 가져 오는 getInstance와 같이).
귀하의 경우 최종 RainOnTrees
클래스에 위임하는 최종 클래스가 아닌 클래스를 만듭니다 . 또는 최종이 아닌 것으로 만들 수 있다면 더 좋습니다.
답변
gradle 파일에 이것을 추가하십시오 :
testImplementation 'org.mockito:mockito-inline:2.13.0'
이것은 최종 클래스와 함께 mockito를 작동시키는 구성입니다.
답변
Powermock을 사용하십시오. 이 링크는이를 수행하는 방법을 보여줍니다. https://github.com/jayway/powermock/wiki/MockFinal
답변
후속 조치를 취하십시오. 이 줄을 gradle 파일에 추가하십시오 :
testCompile group: 'org.mockito', name: 'mockito-inline', version: '2.8.9'
나는 mockito-core와 mockito-all의 다양한 버전을 시도했습니다. 둘 다 작동하지 않습니다.
답변
final
다른 클래스의 확장을 막고 싶기 때문에 당신이 만든 것 같아요 RainOnTrees
. 같이 효과적인 자바 제안 (항목 15)을하지 않고 확장을위한 클래스 가까이를 유지하는 또 다른 방법이있다 final
:
-
final
키워드를 제거하십시오 . -
생성자 만들기
private
.super
생성자 를 호출 할 수 없으므로 클래스를 확장 할 수 없습니다 . -
클래스를 인스턴스화하는 정적 팩토리 메소드를 작성하십시오.
// No more final keyword here. public class RainOnTrees { public static RainOnTrees newInstance() { return new RainOnTrees(); } private RainOnTrees() { // Private constructor. } public void startRain() { // some code here } }
이 전략을 사용하면 Mockito를 사용하고 상용구 코드를 거의 사용하지 않고 수업을 계속 닫을 수 있습니다.