Как проверить, что в MailService передается статическое значение константы sendMail, не требуя префикса класса для константы? - PullRequest
1 голос
/ 02 января 2011

Мой модуль Grails Test тестирует MailService с помощью Expando и переопределяет метод sendMail.Исходный код использует статическую константу с именем EMAIL_SUBJECT без префикса.Однако, когда я запускаю тест и удаляю из Something.EMAIL_SUBJECT «Что-то».он не соответствует утверждению о том, что mockMailService.subject был передан null . Как мне улучшить тест, чтобы получить "Something".в 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 Ответ

2 голосов
/ 02 января 2011

Такое поведение странно только на первый взгляд. Основной причиной является стратегия разрешения 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
}
...