Как проверить, что статическое значение константы передается в 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
}