Grails — модульное тестирование метода контроллера с использованием плагина reCAPTCHA

#unit-testing #grails #configuration #controller #recaptcha

#модульное тестирование #grails #конфигурация #контроллер #recaptcha

Вопрос:

Я хотел бы провести модульное тестирование следующего метода:

 def handleEmailSharing = { EmailSharingCommand esc ->
        if (params.send) {
            def recaptchaOK = true
            if (!recaptchaService.verifyAnswer(session, request.getRemoteAddr(), params)) {
                recaptchaOK = false
            }

         }
...
  

Именно так я и пытаюсь это сделать:

 import com.megatome.grails.RecaptchaService

class EmailSharerControllerTests extends ControllerUnitTestCase {

    protected void setUp() {
     controller.recaptchaService = new RecaptchaService()
   }

void testHandleEmailSharingSendAndSuccess() {
       mockCommandObject(EmailSharingCommand)
        def emailSharingCommand = new EmailSharingCommand(from: "acorrect@emailaddress.fr", 
                                                          to: "   anothercorrect@emailaddress.fr   ,    whichis@notalone.it   ", 
                                                          cc: "", 
                                                          bcc:"someonein@bcc.com.br",
                                                          trimmedListOfToRecipients: ["anothercorrect@emailaddress.fr", "whichis@notalone.it"])
        emailSharingCommand.validate()
}
controller.handleEmailSharing(emailSharingCommand)
  

Но я получаю следующую ошибку:

 Cannot get property 'recaptcha' on null object
java.lang.NullPointerException: Cannot get property 'recaptcha' on null object
    at com.megatome.grails.RecaptchaService.getRecaptchaConfig(RecaptchaService.groovy:33)
    at com.megatome.grails.RecaptchaService.this$2$getRecaptchaConfig(RecaptchaService.groovy)
    at com.megatome.grails.RecaptchaService$this$2$getRecaptchaConfig.callCurrent(Unknown Source)
    at com.megatome.grails.RecaptchaService.isEnabled(RecaptchaService.groovy:100)
    at com.megatome.grails.RecaptchaService$isEnabled.callCurrent(Unknown Source)
    at com.megatome.grails.RecaptchaService.verifyAnswer(RecaptchaService.groovy:81)
    at com.megatome.grails.RecaptchaService$verifyAnswer.call(Unknown Source)
    at bankemist.personalcreditcomparator.EmailSharerController$_closure2.doCall(EmailSharerController.groovy:49)
    at bankemist.personalcreditcomparator.EmailSharerControllerTests.testHandleEmailSharingSendButtonButMissingFromAndTo(EmailSharerControllerTests.groovy:49)
  

Что странно, потому что в основном это говорит о том, что my org.codehaus.groovy.grails.commons.ConfigurationHolder равно null или recaptcha содержащемуся в нем объекту. Строка вызова 33 из RecaptchaService.groovy :

 if (ConfigurationHolder.config.recaptcha) {...}
  

Или (последний 🙂 ) так устанавливается мой RecaptchaConfig.groovy:

 recaptcha {
    // These keys are generated by the ReCaptcha service
    publicKey = "xxx"
    privateKey = "xxx"

    // Include the noscript tags in the generated captcha
    includeNoScript = true
}

mailhide {
    // Generated by the Mailhide service
    publicKey = ""
    privateKey = ""
}

environments {
  development {
    recaptcha {
      // Set to false to disable the display of captcha
      enabled = true

      // Communicate using HTTPS
      useSecureAPI = false
    }
  }
  test {
    recaptcha {
      // Set to false to disable the display of captcha
      enabled = true

      // Communicate using HTTPS
      useSecureAPI = false
    }
  }
  

Мне не удается обойти эту проблему.
Я попытался импортировать configurationHolder в тестовый файл, но это ничего не меняет. Любая помощь с благодарностью.

Ответ №1:

Модульные тесты не будут иметь ConfigurationHolder, поскольку они не выполняются внутри запущенной платформы. В модульных тестах лучшим вариантом является макет RecaptchaService, поэтому, как это делается в вашем методе тестирования:

 def recapMock = mockFor(RecaptchaService)
recapMock.demand.verifyAnswer(1..1) { session, remoteAddr, params ->
     return true // Or false if you want it to fail in your test
}
controller.recaptchaService = recapMock.createMock()
// Then run your test
controller.handleEmailSharing(emailSharingCommand)
  

Ответ №2:

Вы должны ввести recaptchaService и смоделировать verifyAnswer, чтобы вернуть все, что вы хотите вернуть для своего тестового примера.

      def recaptchaServiceMock = mockFor(recaptchaService)

            recaptchaServiceMock.demand.verifyAnswer() {Session session, 
                                                        Map params->
                return true
            }

      currentService.recaptchaService = recaptchaServiceMock.createMock()