Невозможно заполнить 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.

Другие вопросы по тегам