Невозможно заполнить java.util.getTimeZone в Grails 3 для тестов на спок в Taglib
Я застрял где-то в Grails 3 Спок Тестирование на Taglibs. Я хочу проверить закрытие taglib, которое выглядит так:
ATagLib.groovy:
Closure a = {attrs ->
java.util.TimeZone utc = java.util.TimeZone.getTimeZone(FraudnetConstants.TIMEZONE_UTC)
if (attrs.somevar) {
out << "${g.message(code: 'some.code')} ${g.formatDate([date: attrs.date, format: "h:mma", timeZone: utc])}"
} else if (attrs.freq == SomeConstants.VAL || attrs.freq == SomeConstants.VAL) {
out << g.formatDate([date: attrs.date, format: "E '@' h:mma", timeZone: utc])
} else {
out << "${g.message(code: 'some.other.code')} ${g.formatDate([date: attrs.date, format: "h:mma", timeZone: utc])}"
}
}
Мой ATagLibSpec.groovy выглядит так:
@TestFor(ATagLib)
class ATagLibSpec {
def setup() {
java.util.TimeZone.metaClass.'static'.getTimeZone = {a -> return null }
}
void 'testmethod'() {
expect:
taglib.a()
}
}
Исключение, которое я получаю при запуске тестовых сценариев: java.lang.NullPointerException: невозможно вызвать метод getTimeZone() для нулевого объекта в org.grails.plugins.web.taglib.FormatTagLib$_closure2.doCall(FormatTagLib.groovy:170) в groovy..lang.Closure.call(Closure.java:414) по адресу org.grails.taglib.TagOutput.captureTagOutput(TagOutput.java:64) по адресу org.grails.taglib.TagLibraryMetaUtils.methodMissingForTagLib(TagLibe).grails.taglib.NamespacedTagDispatcher.methodMissing(NamespacedTagDispatcher.groovy:59)
Может кто-то указать здесь, что не так с вышеупомянутым способом предварительной установки getTimeZone.
2 ответа
Вместо того, чтобы использовать метапрограммирование, лучше всего вставить TimezoneFactoryService в вашу библиотеку тегов. По моему опыту, необходимость метапрограммирования в тесте является признаком запаха кода: ваш код использует статический метод для создания экземпляра объекта вместо внедрения зависимости.
Ваш код может выглядеть так:
Closure a = {attrs->
java.util.TimeZone utc = timezoneFactoryService.getTimeZone(FraudnetConstants.TIMEZONE_UTC)
}
Это позволит вам смоделировать ваш заводской сервис в вашей спецификации более удобным способом, используя обычный спок-макет.
@TestFor(ATagLib)
class ATagLibSpec {
def setup() {
taglib.timezoneFactoryService=Stub(TimezoneFactoryService) {
getTimeZone(_) >> null
}
}
void 'testmethod'() {
expect:
taglib.a()
}
}
Если вы все еще хотите использовать метапрограммирование, имейте в виду, что сигнатура метода должна полностью соответствовать (также типам параметров), поэтому:
java.util.TimeZone.metaClass.'static'.getTimeZone = {a -> return null }
java.util.TimeZone.getTimeZone("America/Los_Angeles")
Этот код получит часовой пояс для Америки / Лос-Анджелеса, но
java.util.TimeZone.metaClass.'static'.getTimeZone = {String a -> return null }
java.util.TimeZone.getTimeZone("America/Los_Angeles")
этот вернет ноль, поскольку мы правильно изменили метод с помощью метапрограммирования.
Также помните, что вы должны использовать введенную переменную tagLib, а не taglib.