0

통합 테스트에서 외부 서비스에 대한 호출을 모의하려고합니다.이 서비스는 grails 웹 플로우에서 사용됩니다. 서비스는 흐름 또는 대화 범위에 있지 않지만 종속성 삽입을 통해 추가됩니다 (here 참조).서비스의 메타 클래스를 재정의하지 못하게하는 방법

저는 ExpandoMetaClass를 사용하여 metaClass를 대체하여 서비스를 재정의하는 방법을 찾아 냈습니다. 변경 사항은 테스트가 단독으로 실행될 때만 작동합니다.이 테스트 이전에 동일한 서비스를 사용하는 다른 테스트가 실행되면 metaClass 변경 사항이 사라집니다. 메타 클래스를 오버라이드 (override)

부 :

static { 
    ExpandoMetaClass someService = new ExpandoMetaClass(Object, false) 
    someService.invokeMethod = { String name, args -> 
     def result = 'success' 
     if(name.equals('accessAnotherSystem') 
     { 
      StackTraceUtils.sanitize(new Throwable()).stackTrace.each 
      { 
       if(it.methodName.equals('test_method_I_Want_failure_in') 
       { 
        result = 'exception' 
       } 
      } 
      return result 
     } 

     def validMethod = SomeService.metaClass.getMetaMethod(name, args) 
     if (validMethod != null) 
     { 
      validMethod.invoke(delegate, args) 
     } 
     else 
     { 
      SomeService.metaClass.invokeMissingMethod(delegate, name, args) 
     } 
    } 
    someService.initialize() 
    SomeService.metaClass = someService 
} 

관련 질문 : How to change a class's metaClass per test

테스트 내 변화를 유지하는 방법이 있나요, 또는 서비스를 대체 할 다른 방법이있다.

+0

어디에서이 코드를 앱에 추가 했습니까? –

+0

시험 방법 이전의 시험 수업. –

답변

0

테스트 방법에 따라 테스트 케이스에서 서비스를 재정의하려는 경우 더 간단한 방법이 있습니다. 예를 들어 봐 : 당신은 어떤 서비스 시험 방법이 동일한 작업을 수행 할 수

class SomeControllerSpec extends Specification { 

    def someService 

    void "test any external method for success response"() { 
     given: "Mocked service method" 
     someService.metaClass.accessAnotherSystem = { arg1, arg2 -> 
      return "some success response" 
     } 

     when: "Any controller method is called which calls this service method" 
     // Your action which calls that service method 

     then: "Result will processed coming from mocked method" 
     // Your code 
    } 
} 

. 테스트 케이스를 작성하고있는 동일한 서비스 메소드를 조롱하려면 여기를 클릭하십시오.

class SomeServiceSpec extends Specification { 

    def someService 

    void "test external method call"() { 
     given: "Mocked service method" 
     someService.metaClass.methodA = { arg1, arg2 -> 
      return "some success response" 
     } 

     when: "A method is called which invokes the another method" 
     // Your another service method which call the same method 
     someService.methodB() // Where methodB() invokes the methodA() internally in your code 

     then: "Result will processed coming from mocked method" 
     // Your code 
    } 
}