Как проверить, что статическое значение константы передается в MailService. SendMail закрывается без запроса префикса класса на константе?

Мой модульный тест Grails делает макет MailService с помощью Expando и переопределяет метод sendMail. Исходный код использует статическую константу с именем EMAIL_SUBJECT без префикса. Однако, когда я запускаю тест и удаляю из Something.EMAIL_SUBJECT "Что-то". оно не соответствует утверждению о том, что mockMailService.subject был передан нулевой. Как я могу улучшить тест, чтобы "Что-то". не нужно на EMAIL_SUBJECT?

Фрагмент кода теста:

def createMockMailService() {

    def mockMailService = new Expando()

    mockMailService.sendMail = { callable ->

        callable.delegate = mockMailService
        callable.resolveStrategy = Closure.DELEGATE_FIRST
        callable.call()
    }

    mockMailService.subject = { header -> }

    mockMailService
}

void testThis() {
    def mockMailService = createMockMailService()

    mockMailService.subject = { assert it == "value of constant"  }

    Something something = new Something()
    something.mailService = mockMailService

    something.doSomethingThatCallsMailService()
}

Тестируемый код:

class Something {

    static def EMAIL_SUBJECT = "value of constant"

    def mailService = new SomeMailThing()

    def doSomethingThatCallsMailService() {
            mailService.sendMail {
            subject Something.EMAIL_SUBJECT // Remove Something prefix
        }
    }

}

1 ответ

Решение

Такое поведение странно только на первый взгляд. Основной причиной является DELEGATE_FIRST в этом случае стратегия разрешения объединяется с делегатом, являющимся экземпляром Expando. DELEGATE_FIRST ищет EMAIL_SUBJECT свойство в делегате первым, который является mockMailService, который является Expando. Expando не бросает groovy.lang.MissingPropertyException на отсутствующие свойства, вместо этого он возвращает ноль. Таким образом, свойство находится на делегате и не оценивается на владельца (который будет Something Вы хотите собственность от).

Вы можете изменить стратегию разрешения на OWNER_FIRST, Если вы хотите придерживаться DELEGATE_FIRST потому что оригинал mailService вызывает sendMail При использовании этой стратегии для параметра замыкания вы не можете использовать Expando для службы по умолчанию. Вместо этого вы можете использовать обычный объект и выполнять метапрограммирование в метаклассе.

Это будет выглядеть примерно так:

def createMockMailService() {
   def mockMailService = new Object()
   mockMailService.metaClass.sendMail = { callable ->
      callable.delegate = mockMailService
      callable.resolveStrategy = Closure.DELEGATE_FIRST
      callable.call()
   }
   mockMailService.metaClass.subject = { header -> }
   mockMailService
}
Другие вопросы по тегам