3

통합 테스트에서 컨트롤러의 동작을 테스트하려고합니다. 테스트하려는 작업이 서비스 메소드를 호출하는 간단한 시나리오입니다. 메타 클래스를 사용하여 해당 메서드를 재정의하려하지만 작동하지 않는 것처럼 보입니다. 즉, 메타 클래스를 사용하여 재정의 한 서비스 대신 항상 실제 메서드가 호출됩니다. 여기서 내가 뭘 잘못하고 있니?grails 통합 테스트에서 서비스 메소드를 오버라이드

class MyControllerTests extends GroovyTestCase { 

MyController controller 

void testMethodA() { 
    controller = new MyController() 

    // Mock the service 
    MyService mockService = new MyService() 
    mockService.getMetaClass().find = { String s -> 
     [] 
    } 

    controller = new MyController() 
    controller.myService = myService 

    controller.methodA() 
    } 

추신 :

여기
class MyController { 
    MyService myService 

    def methodA() { 
    def u = myService.find(params.paramA) 
    render view: "profile", model: [viewed: u] 
    } 

내가 통합 테스트를 구현하는 방법은 다음과 같습니다 여기

는 컨트롤러의 방법입니다 그런 다음 컨트롤러를 테스트

@Mock([Book, Author, BookService]) 

: 나는 당신이 당신의 서비스를 조롱하기위한 Grails의 주석을 사용하는 것이 좋습니다 2.9.2

답변

7

우선 내가 integrates with Grails pretty well 외에 정말 테스트 라이브러리의 좋은 작품이다 Spock Framework를 사용하는 것이 좋습니다 모든. 귀하의 시험은 다음과 같습니다 당신이 스팍을 사용하지 않고 유지하려는 경우,

@TestFor(MyController) // TestFor is builtin Grails annotation 
class MyControllerSpec extends Specification { 

    // thanks to TestFor annotation you already have 'controller' variable in scope 

    MyService mockService = Mock(MyService) 

    // setup method is executed before each test method (known as feature method) 
    def setup() { 
     controller.myService = mockService 
    } 

    def 'short description of feature being tested'() { 
     given: 
     mockService.find(_) >> [] // this tells mock to return empty list for any parameter passed 

     when: 
     controller.methodA() 

     then: 
     // here goes boolean statements (asserts), example: 
     controller.response.text.contains 'Found no results' 
    } 
} 

모의 당신은 간단한 방법은 그루비 강제을 사용하는 것이 필요합니다. 이 체크 아웃 :

MyService mockService = [find: { String s -> [] }] as MyService 

맵 강제입니다. 귀하의 경우조차지도조차 필요가없는 단일 방법을 조롱 할 때, 더 간단하게 작성할 수 있습니다.

MyService mockService = { String s -> [] } as MyService 

폐쇄 강제입니다. 음, 매개 변수를 지정하는 것은 처리하지 않는 경우에도 필요하지 않습니다.

MyService mockService = { [] } as MyService 

마지막 문장은 기본적으로 그렇게 빈 목록이 결과로 반환됩니다 지정된 폐쇄를 실행합니다 mockService 호출 어떤 방법보다 의미합니다.

더 간단합니다.

그런데 Spock을 사용할 때 여전히 강제적 인 조롱을 사용할 수 있습니다. Spock mock (Mock() 메소드로 생성)은 예를 들어 상호 작용과 같은 고급 사례를 테스트 할 때 유용합니다.

업데이트 : 통합 테스트의 경우 IntegrationSpec을 확장하고 @TestFor를 사용하지 않아도됩니다.

+1

topr, 고맙습니다. 당신이 제안한 강압 기법을 사용하여 끝내었고 모든 것이 잘 작동했습니다. – Tomato

+1

통합 테스트에 대한 질문이 아닙니까? 코드가 단위 테스트 용인 것처럼 보입니다. –

1

나는 문서 10.1 Unit Testing에서 가져온 다음과 같은 예를 들어, STS에서 Grails는 2.0.0을 사용하고 있습니다 보이는 같은 :

void testSearch() { 
     def control = mockFor(SearchService) 
     control.demand.searchWeb { String q -> ['mock results'] } 
     control.demand.static.logResults { List results -> } 
     controller.searchService = control.createMock() 
     controller.search()  assert controller.response.text.contains "Found 1 results" 
} 
관련 문제