모키토로 마지막 수업을 조롱하는 방법
기말고사 수업이 있어요. 이런 식으로요.
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 2가 파이널 클래스 및 메서드를 지원하게 되었습니다!
그러나 현재로선 이 기능이 "삽입"된 것입니다.Mockito 2의 새로운 기능에서 설명된 바와 같이 활성화하려면 몇 가지 단계가 필요합니다.
최종 클래스 및 메서드를 조롱하는 것은 인큐베이팅 옵션인 기능입니다.이러한 유형의 모의성을 활성화하기 위해 Java 에이전트 계측과 하위 분류의 조합을 사용합니다.이것은 현재의 메커니즘과는 다른 동작으로 다른 제한이 있기 때문에 경험과 사용자 피드백을 수집하기 위해 이 기능을 명시적으로 활성화해야 합니다.파일을 작성함으로써 mockito 확장 메커니즘을 통해 실행할 수 있습니다.
src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
[ ] [ 일 、 [ 。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 v2에서만 가능합니다.
gradle 파일에 다음 추가:
testImplementation 'org.mockito:mockito-inline:2.13.0'
이것은 Mockito v1에서는 가능하지 않습니다.Mockito FAQ:
Mockito의 한계점은 무엇입니까?
Java 1.5+ 필요
최종 수업을 모의할 수 없습니다.
...
빌드 파일에 다음을 추가합니다.
- 그래들을 사용하는 경우:
build.gradle
testImplementation 'org.mockito:mockito-inline:2.13.0'
- maven을 사용하는 경우:
pom.xml
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-inline</artifactId>
<version>2.13.0</version>
<scope>test</scope>
</dependency>
이것은 모키토가 최종 수업과 함께 작동하도록 하기 위한 구성입니다.
이 이 the를 있다면,Could not initialize inline Byte Buddy mock maker. (This mock maker is not supported on Android.)
Byte Buddy 종속성을 에 추가합니다.build.gradle
삭제:
testImplementation 'net.bytebuddy:byte-buddy-agent:1.10.19'
src: https://mvnrepository.com/artifact/net.bytebuddy/byte-buddy
혼자서는 할 수 없기 때문에, 모키토와의 최종 수업은 조롱할 수 없습니다.
제가 하는 일은 최종 클래스가 아닌 클래스를 만들어 최종 클래스를 랩하고 위임자로 사용하는 것입니다.그 예로는 class가 있습니다.이것이 나의 mockable class입니다.
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();
}
}
단점은 보일러 플레이트코드가 많다는 것입니다.장점은 어플리케이션비즈니스와 관련된 메서드를 추가할 수 있다는 것입니다(접속 대신 사용자를 필요로 하는 getInstance 등).토큰(위의 경우).
, 저는 인 것을 .RainOnTrees
이치노아니면 비최종까지 갈 수 있다면 더 좋을 것 같아요.
Powermock을 사용합니다.이 링크는, 그 방법을 나타내고 있습니다.https://github.com/jayway/powermock/wiki/MockFinal
Mockito 3 이상에서도 같은 문제가 발생하여 이 링크에서 수정하였습니다.
최종 클래스 및 메서드를 조롱하기 위해 Mockito를 사용하기 전에> 를 설정할 필요가 있습니다.
프로젝트의 src/test/resources/mockito-extensions 디렉토리에 org.mockito라는 텍스트 파일을 추가해야 합니다.플러그 인을 클릭합니다.MockMaker를 사용하여 한 줄의 텍스트를 추가합니다.
mock-maker-inline
Mockito는 확장자 디렉토리가 로드될 때 구성 파일을 확인합니다.이 파일은 최종 메서드 및 클래스를 조롱할 수 있도록 합니다.
그냥 추적하려고요.gradle 파일에 다음 행을 추가하십시오.
testCompile group: 'org.mockito', name: 'mockito-inline', version: '2.8.9'
모키토코어와 모키토올의 다양한 버전을 시도해 보았습니다.둘 다 효과가 없어요.
저도 같은 문제가 있었어요.제가 놀리려고 했던 수업은 단순한 수업이었기 때문에, 저는 그냥 예시를 만들어서 돌려드렸습니다.
가 final
가 확장되는 을 막고 때문입니다.RainOnTrees
Effective Java(항목 15)가 시사하는 바와 같이 클래스를 만들지 않고 확장하기 위해 클래스를 닫는 다른 방법이 있습니다.final
:
를제 remove remove remove를 remove remove 를 remove 。
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를 사용할 수 있고, 보일러 플레이트 코드를 거의 사용하지 않고도 수업을 연장할 수 있습니다.
경우에 따라서는 적용할 수 있는 다른 회피책은 최종 클래스에서 구현되는 인터페이스를 만들고 구체적인 클래스가 아닌 인터페이스를 사용하도록 코드를 변경한 후 인터페이스를 조롱하는 것입니다.이것에 의해, 계약(인터페이스)과 실장(최종 클래스)을 분리할 수 있습니다.물론 최종 클래스로 바인드하는 경우는 적용되지 않습니다.
Android + Kotlin에서 동일한 문제(Mockito + Final Class)에 직면한 사용자를 위한 시간 절약.Kotlin에서와 같이 클래스는 기본적으로 최종입니다.Google Android 샘플 중 Architecture 컴포넌트에서 솔루션을 찾았습니다.솔루션 선택 : https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample
다음 주석을 만듭니다.
/**
* This annotation allows us to open some classes for mocking purposes while they are final in
* release builds.
*/
@Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class OpenClass
/**
* Annotate a class with [OpenForTesting] if you want it to be extendable in debug builds.
*/
@OpenClass
@Target(AnnotationTarget.CLASS)
annotation class OpenForTesting
그래들 파일을 수정합니다.https://github.com/googlesamples/android-architecture-components/blob/master/GithubBrowserSample/app/build.gradle 에서 예를 들어보겠습니다.
apply plugin: 'kotlin-allopen'
allOpen {
// allows mocking for classes w/o directly opening them for release builds
annotation 'com.android.example.github.testing.OpenClass'
}
이제 임의의 클래스에 주석을 달아 테스트용으로 열 수 있습니다.
@OpenForTesting
class RepoRepository
시험해 보세요.
Mockito.mock(SomeMockableType.class,AdditionalAnswers.delegatesTo(someInstanceThatIsNotMockableOrSpyable));
그것은 나에게 효과가 있었다."SomeMockableType.class"는 조롱 또는 스파이 대상의 부모 클래스이며, someInstanceThatIsNotMockableOrSpyable은 조롱 또는 스파이 대상의 실제 클래스입니다.
자세한 내용은 여기를 참조하십시오.
사실 한 가지 방법이 있어 스파이 활동을 할 때 쓰는 방법이지다음 두 가지 전제 조건이 충족되어야만 작동합니다.
- 어떤 종류의 DI를 사용하여 최종 클래스의 인스턴스를 주입합니다.
- 최종 클래스는 인터페이스를 구현합니다.
유효한 Java에서 항목 16을 회수하십시오.래퍼(최종 아님)를 생성하여 모든 콜을 최종 클래스의 인스턴스로 전송할 수 있습니다.
public final class RainOnTrees implement IRainOnTrees {
@Override public void startRain() { // some code here }
}
public class RainOnTreesWrapper implement IRainOnTrees {
private IRainOnTrees delegate;
public RainOnTreesWrapper(IRainOnTrees delegate) {this.delegate = delegate;}
@Override public void startRain() { delegate.startRain(); }
}
이제 마지막 수업을 비웃을 수 있을 뿐만 아니라 그것을 염탐할 수도 있습니다.
public class Seasons{
RainOnTrees rain;
public Seasons(IRainOnTrees rain) { this.rain = rain; };
public void findSeasonAndRain(){
rain.startRain();
}
}
IRainOnTrees rain = spy(new RainOnTreesWrapper(new RainOnTrees()) // or mock(IRainOnTrees.class)
doNothing().when(rain).startRain();
new Seasons(rain).findSeasonAndRain();
최종 클래스 및 메서드의 모킹에 대응하는 새로운 인큐베이션 기능을 갖춘 Mockito2를 사용하는 경우 가능합니다.
★★★★★★★★★★★★★★★★★★:
""이라는. "buff.buff.to"는 "buff.입니다.플러그 인을 클릭합니다.MockMaker'는 Mockito-extensions입니다.이 폴더는 클래스 경로에서 사용할 수 있어야 합니다.
2. 한 . 2. 위에서 작성한 파일의 내용은 다음과 같이 한 줄이어야 합니다.
메이커
mockito 확장 메커니즘을 활성화하고 이 옵트인 기능을 사용하려면 위의 두 단계가 필요합니다.
샘플 클래스는 다음과 같습니다.-
FinalClass.java
public final class FinalClass {
public final String hello(){
System.out.println("Final class says Hello!!!");
return "0";
}
}
푸자바
public class Foo {
public String executeFinal(FinalClass finalClass){
return finalClass.hello();
}
}
FooTest.java
public class FooTest {
@Test
public void testFinalClass(){
// Instantiate the class under test.
Foo foo = new Foo();
// Instantiate the external dependency
FinalClass realFinalClass = new FinalClass();
// Create mock object for the final class.
FinalClass mockedFinalClass = mock(FinalClass.class);
// Provide stub for mocked object.
when(mockedFinalClass.hello()).thenReturn("1");
// assert
assertEquals("0", foo.executeFinal(realFinalClass));
assertEquals("1", foo.executeFinal(mockedFinalClass));
}
}
도움이 됐으면 좋겠다.
여기 있는 완전한 기사는 조롱할 수 없는 것이다.
네, 여기도 같은 문제지만, 우리는 모키토와의 마지막 수업을 조롱할 수 없습니다.정확히 말하면, Mockito는 다음을 조롱/스파이 할 수 없습니다.
- 최종 수업
- 익명의 수업
- 원시형
하지만 래퍼 클래스를 사용하면 비용이 많이 들 것 같으니 대신 Power Mockito를 구입하세요.
원칙적으로 좀 더 생각해 볼 필요가 있을 것 같아요.대신 최종 클래스는 그의 인터페이스와 모의 인터페이스를 사용합니다.
이 경우:
public class RainOnTrees{
fun startRain():Observable<Boolean>{
// some code here
}
}
더하다
interface iRainOnTrees{
public void startRain():Observable<Boolean>
}
및 모의 인터페이스:
@Before
fun setUp() {
rainService= Mockito.mock(iRainOnTrees::class.java)
`when`(rainService.startRain()).thenReturn(
just(true).delay(3, TimeUnit.SECONDS)
)
}
JMockit 보세요.그것은 많은 예시와 함께 광범위한 문서를 가지고 있다.여기 문제의 해결책 예가 있습니다(심플화를 위해 컨스트럭터를 추가했습니다).Seasons
조롱의 RainOnTrees
★★★★★★★★★★★★★★★★★★:
package jmockitexample;
import mockit.Mocked;
import mockit.Verifications;
import mockit.integration.junit4.JMockit;
import org.junit.Test;
import org.junit.runner.RunWith;
@RunWith(JMockit.class)
public class SeasonsTest {
@Test
public void shouldStartRain(@Mocked final RainOnTrees rain) {
Seasons seasons = new Seasons(rain);
seasons.findSeasonAndRain();
new Verifications() {{
rain.startRain();
}};
}
public final class RainOnTrees {
public void startRain() {
// some code here
}
}
public class Seasons {
private final RainOnTrees rain;
public Seasons(RainOnTrees rain) {
this.rain = rain;
}
public void findSeasonAndRain() {
rain.startRain();
}
}
}
RC와 Luigi R이 제공하는 솔루션.Viggiano가 함께 있는 것이 가장 좋은 생각일 것이다.
모키토는 설계상 최종수업을 모의할 수 없지만 위임접근은 가능하다.여기에는 다음과 같은 이점이 있습니다.
테스트의 경우 테스트 대상 시스템에 의도적으로 콜을 전송합니다.따라서 설계상 장식은 아무 것도 하지 않습니다.
따라서 사용자가 API를 확장하지 않고 꾸밀 수 있음을 테스트에서 증명할 수도 있습니다.
보다 주관적인 설명:저는 틀을 최소한으로 유지하는 것을 선호하기 때문에 JUnit과 Mockito는 보통 저에게 충분합니다.사실, 이런 식으로 제한하는 것은 때때로 나에게도 좋은 결과를 다시 생각하게 만들기도 한다.
테스트 폴더 아래에서 유닛 테스트를 실행하려고 하면 정상입니다.그냥 따라가서 확장자를 추가하세요.
하지만 Android test 폴더에 있는 컨텍스트나 액티비티와 같은 안드로이드 관련 클래스와 함께 실행하고 싶다면, 정답은 당신을 위한 것입니다.
mockito를 정상적으로 실행하기 위해 다음 종속성을 추가합니다.
실장 'org24.'org.mockito:mockito-core:2.24.5'
Implementation 24 테스트 실장 "org.mockito:mockito-inline:2.24.5"
이 GitHub 문제에 따라 mockito-android에서는 최종 클래스 모킹은 지원되지 않습니다.대신 Mockk를 사용하세요.
유닛 테스트와 UI 테스트 모두 문제없이 Mockk를 사용할 수 있습니다.
,, Android의 Mockito는 할 수 .mockito-inline
한 ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★가 있습니다mockito-android
"최종 클래스" 문제도 해결하지 못하는 버전입니다.효과가 있을 것 같은 유일한 해결책은 덱스메이커 라이브러리입니다.단, Android P(Android 9, API 28) 이상에서만 동작하는 것이 한계입니다.다음과 같이 가져올 수 있습니다.
androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito-inline:2.28.1"
최종 수업에서도 사용할 수 없는 "dexmaker-mockito" 버전도 있으므로 주의하시기 바랍니다."dexmaker-mockito-inline"을 반드시 Import하십시오.
다른 사람들이 말했듯이, 이것은 Mockito와 함께 즉시 실행되지는 않을 것입니다.리플렉션을 사용하여 테스트 대상 코드에서 사용되는 객체에 특정 필드를 설정할 것을 권장합니다.이 기능을 자주 사용하는 경우 라이브러리에서 이 기능을 래핑할 수 있습니다.
덧붙여서, 만약 당신이 최종 채점 수업자라면, 그것을 그만두세요.제가 이 질문을 하게 된 것은 API를 사용하고 있기 때문입니다.API에서는 모든 것을 최종 마킹하여 정당한 확장(Mocking)을 필요로 하지 않도록 하고 있기 때문입니다.또한 개발자가 제가 클래스를 연장할 필요가 없다고 생각하지 않았기를 바랍니다.
우리는 mockito-inline을 코인 테스트에서 제외했기 때문입니다.1개의 그래들모듈에서는 실제로 이 기능이 필요했습니다.이유는 릴리즈 빌드에서만 실패했습니다(IDE에서의 디버깅빌드는 동작했습니다).-P
최종 클래스의 경우 아래를 mock and call static 또는 non static에 추가합니다.
레벨 {패키지 이름}) 합니다. @SuppressStatucInitializationFor ( = {suppressStatucInitializationFor } ) 。
- PowerMockito.mockStatic(classname.class)을 조롱합니다.
이할 때 할 때 합니다.3- 으면 안 돼요.
즐거운 시간 되세요.
저는 이 메시지를 극복할 수 있었습니다.
org.syslogito.exceptions.base.MockitoException: mock/spy 클래스 org.slf4j.impl을 실행할 수 없습니다.Log4jLoggerAdapter Mockito는 다음과 같은 이유로 모의/스파이할 수 없습니다.
- 최종 또는 익명의 클래스
: " 기 from from from from fromlog = spy(log);
대신 이것을 사용하면:
log = mock(Logger.class);
그럼 효과가 있군요.
디폴트 로거 어댑터는 최종 클래스의 인스턴스이기 때문에 '스파이'는 할 수 없지만 전체를 조롱할 수는 있습니다.생각해 봐...
즉, 다른 "비최종" 인스턴스로 대체할 수도 있습니다.아니면 단순화된 버전 등. WWIW...
javaTest update kotlin 클래스 prob의 답을 찾고 있는 모든 신입사원을 위한 2021년입니다.오래된 코드 베이스에 대해서요.
이제 테스트 클래스를 Java에서 kotlin으로 서서히 이행할 때입니다.
- javaTest와 유사한 새로운 kotlin 테스트 클래스를 만드십시오.
- 이 오래된 Java 테스트 케이스 변경의 일부로 현재 영향을 주고 있는 쓰기 테스트만 사용하십시오.
MockK 를 사용해 주세요.https://mockk.io/ 를 참조해 주세요.
위의 내용은 새로운 kotlin 클래스를 오래된 Java 구현에 연결하여 테스트 클래스를 원활하게 업데이트하려는 경우에 해당됩니다.
위의 시나리오는 테스트에서 잘 학습되었습니다.
주의: 이것이 정답이 아닌 것은 알지만, 레거시 코드 베이스에 대해 작업하면서 배운 전략을 공유할 가치가 있습니다.
final을 시도하지 않았지만, 비공개적인 경우 reflection을 사용하여 reflection을 사용하여 reflection the modifier worked!를 추가로 확인했는데, final에는 작동하지 않습니다.
언급URL : https://stackoverflow.com/questions/14292863/how-to-mock-a-final-class-with-mockito
'source' 카테고리의 다른 글
Linux에서 GDB를 시작할 때 명령줄 인수를 전달하려면 어떻게 해야 합니까? (0) | 2022.08.20 |
---|---|
사람들이 C 포인터에 대해 어려워하는 점은 무엇인가? (0) | 2022.08.20 |
부팅 시 Eclipse가 중단되는 것을 방지하려면 어떻게 해야 합니까? (0) | 2022.08.20 |
Netflow 레코드는 옥텟(jnca)을 가져올 수 없습니다. (0) | 2022.08.20 |
Vue에서 로컬로 저장된 xml 파일을 가져오고 편집하려면 어떻게 해야 합니까? (0) | 2022.08.20 |