자바 프로젝트에서 작업하고 Spock 프레임 워크를 사용하여 Groovy에서 단위 테스트를 작성하기 시작했습니다. 하지만 Spock의 조롱 기능에 문제가있어 누군가 내가 잘못하고있는 것을 알아낼 수 있기를 바랍니다.Spock이 구체적인 수업을 올바르게 조롱하지 않았습니까?
나는 세 개의 자바 클래스를하십시오 FooContext
(즉, foo
속성을 포함)하는 HasFooContext
클래스 (즉, fooContext
속성이 포함), 및 HasFooContext
에서 상속 (그리고 fooContext
를 호출하는 동작이있다)을 FooService
:
public class FooContext {
private Object foo = new Object();
public Object getFoo() {
return foo;
}
}
public abstract class HasFooContext {
private FooContext fooContext;
public void setFooContext(FooContext fooContext) {
this.fooContext = fooContext;
}
public Object getFoo() {
Object foo = fooContext.getFoo();
assert foo != null : "no foo available";
return foo;
}
}
public class FooService extends HasFooContext {
public void doFoo() {
getFoo();
}
}
이
FooService
의
doFoo
방법은 차례로 그
fooContext
속성의
getFoo
메소드를 호출 기본 클래스
HasFooContext
에있는
getFoo
메서드를 호출하는 것을 여기에서 볼 수있다
. 또한 fooContext.getFoo()
에서 반환 된 값이 null이 아니라고 주장합니다. 예상대로
public class FooServiceJavaUnitTest {
private FooContext fooContext;
private FooService fooService;
@Before
public void setup() {
Object foo = new Object();
fooContext = mock(FooContext.class);
when(fooContext.getFoo()).thenReturn(foo);
fooService = new FooService();
fooService.setFooContext(fooContext);
}
@Test
public void doFooInvokesGetFoo() {
fooService.doFoo();
verify(fooContext, times(1)).getFoo();
}
}
이 테스트가 성공적으로 실행 :
나는doFoo
를 호출하면
fooContext.getFoo()
메소드를 호출하는지 확인하기 위해, Mockito를 사용하여 자바에 다음과 같은 단위 테스트를 썼다.
은 그때 사용, 그루비에서 다음 단위 테스트를 작성 스팍 :
class FooServiceGroovyUnitTest extends Specification {
private FooContext fooContext;
private FooService fooService;
def setup() {
// Create a mock FooContext.
fooContext = Mock(FooContext)
fooContext.getFoo() >> new Object()
fooService = new FooService()
fooService.fooContext = fooContext
}
def "doFoo invokes getFoo"() {
when: "call doFoo"
fooService.doFoo()
then: "getFoo is invoked"
1 * fooContext.getFoo()
}
}
다음과 같이 테스트가 실패 :
FooServiceGroovyUnitTest.doFoo이 getFoo 호출 : 21 사용할 수 없음 foo는
즉, Groovy/Spock을 사용할 때는 실패하지만 Java/Mockito를 사용할 때는 실패합니다.
public abstract class HasFooContext {
...
public Object getFoo() {
Object foo = fooContext.getFoo();
assert foo != null : "no foo available";
return foo;
}
}
FooContext
의 foo
속성은 final이 아니므로 getFoo()
메서드는 final이 아니어야하므로 생성 된 프록시는 해당 메서드를 가로 챌 때 아무런 문제가 없어야합니다 (Java/Mockito 테스트 별).
class FooServiceGroovyUnitTest extends Specification {
...
def setup() {
// Spy on a real FooContext.
fooContext = Spy(FooContext)
fooService = new FooService()
fooService.fooContext = fooContext
}
}
을 다음 그루비/스팍 단위 테스트를 통과 다음과 같이 내가 구체적인 FooContext
에 스파이로 모의 FooContext
를 교체하면 것을
참고. 이는 구체적 클래스를 조롱하거나 구체적인 클래스를 염탐 할 때 동작이 다르다는 것을 의미합니다. Spock 문서에 따르면 모의 API는 동적 프록시를 사용하는 인터페이스와 CGLIB를 사용하는 클래스를 모두 지원합니다.
Java/Mockito 유닛 테스트와 Groovy/Spock 유닛 테스트는 동등하지만, FooContext
클래스를 조롱 할 때 Groovy/Spock 유닛 테스트를 통과 할 수 없습니다.
내가 뭘 잘못하고 있는지에 대한 제안이 있으십니까?같은 상호 작용의
의견을 보내 주셔서 감사합니다. 제안 된 변경이 이루어지면 Groovy/Spock 테스트가 통과됩니다. 설치 프로그램의'getFoo() >> new Object()'표현식이 mockito'when (...). thenReturn (...)'표현식과 동등하게 동작한다고 생각했습니다. 그래서'1 * fooContext.getFoo()'가'1 * fooContext.getFoo() >> null'과 같은 경우입니까? –
편집 : 문서 (http://docs.spockframework.org/en/latest/interaction_based_testing.html#combining-mocking-and-stubbing 참조)에 따라 'null'이 실제로 반환됩니다. –