Development Tip

연결 호출을위한 모의 또는 스텁

yourdevel 2020. 12. 3. 20:43
반응형

연결 호출을위한 모의 또는 스텁


protected int parseExpire(CacheContext ctx) throws AttributeDefineException {
    Method targetMethod = ctx.getTargetMethod();
    CacheEnable cacheEnable = targetMethod.getAnnotation(CacheEnable.class);
    ExpireExpr cacheExpire = targetMethod.getAnnotation(ExpireExpr.class);
    // check for duplicate setting
    if (cacheEnable.expire() != CacheAttribute.DO_NOT_EXPIRE && cacheExpire != null) {
        throw new AttributeDefineException("expire are defined both in @CacheEnable and @ExpireExpr");
    }
    // expire time defined in @CacheEnable or @ExpireExpr
    return cacheEnable.expire() != CacheAttribute.DO_NOT_EXPIRE ? cacheEnable.expire() : parseExpireExpr(cacheExpire, ctx.getArgument());
}

그것이 테스트하는 방법입니다.

Method targetMethod = ctx.getTargetMethod();
CacheEnable cacheEnable = targetMethod.getAnnotation(CacheEnable.class);

CacheContext, Method 및 CacheEnable 세 가지를 조롱해야합니다. 테스트 케이스를 훨씬 간단하게 만들 아이디어가 있습니까?


Mockito 는 연결된 스텁을 처리 할 수 ​​있습니다 .

Foo mock = mock(Foo.class, RETURNS_DEEP_STUBS);

// note that we're stubbing a chain of methods here: getBar().getName()
when(mock.getBar().getName()).thenReturn("deep");

// note that we're chaining method calls: getBar().getName()
assertEquals("deep", mock.getBar().getName());

체인의 첫 번째 메서드 인 AFAIK는 두 번째 체인 메서드 호출에서 값을 반환하도록 설정된 모의를 반환합니다.

Mockito의 저자는 이것이 레거시 코드에만 사용 되어야한다고 지적합니다 . 그렇지 않으면 더 좋은 방법은 동작을 CacheContext에 푸시하고 작업 자체를 수행하는 데 필요한 정보를 제공하는 것입니다. CacheContext에서 가져온 정보의 양은 클래스에 기능 부러움 이 있음을 나타냅니다 .


테스트 케이스를 더 간단하게 만드는 방법은 방법을 리팩터링하는 것입니다.

메서드를 테스트하는 데 문제가있을 때마다 코드 냄새가 나는데 왜 테스트하기 어려운지 묻습니다. 코드를 테스트하기 어려운 경우 사용 및 유지 관리가 어려울 수 있습니다.

이 경우 여러 수준의 메서드 체인이 있기 때문입니다. 아마도 ctx, cacheEnable 및 cacheExpire를 매개 변수로 전달할 수 있습니다.


JMockit을 사용하기가 더 쉬웠으며 완전히 전환되었습니다. 그것을 사용하여 테스트 사례를 참조하십시오.

https://github.com/ko5tik/andject/blob/master/src/test/java/de/pribluda/android/andject/ViewInjectionTest.java

여기서는 Android SKD에서 온 활동 기본 클래스를 모의 처리하고 완전히 스텁 처리했습니다. JMockit을 사용하면 최종, 개인, 추상 또는 기타 모든 것을 조롱 할 수 있습니다.

테스트 케이스에서는 다음과 같습니다.

public void testFoo(@Mocked final Method targetMethod, 
                    @Mocked  final CacheContext context,
                    @Mocked final  CacheExpire ce) {
    new Expectations() {
       {
           // specify expected sequence of infocations here

           context.getTargetMethod(); returns(method);
       }
    };

    // call your method
    assertSomething(objectUndertest.cacheExpire(context))

Just in case you are using Kotlin. MockK doesn't say anything about chaining being a bad practice and easily allows you to do this.

val car = mockk<Car>()

every { car.door(DoorType.FRONT_LEFT).windowState() } returns WindowState.UP

car.door(DoorType.FRONT_LEFT) // returns chained mock for Door
car.door(DoorType.FRONT_LEFT).windowState() // returns WindowState.UP

verify { car.door(DoorType.FRONT_LEFT).windowState() }

confirmVerified(car)

참고URL : https://stackoverflow.com/questions/7926891/mock-or-stub-for-chained-call

반응형