Как сделать unit test услугу Grails, которая использует конвертер?
У меня есть служба Grails, которая отправляет электронные сообщения с помощью сторонней службы, выполняя HTTP-вызов:
class EmailService {
def sendEmail(values) {
def valueJson = values as JSON
... // does HTTP call to 3rd party service
}
}
Я написал unit test, чтобы протестировать эту службу (поскольку интеграционный тест включает Hibernate и всю инфраструктуру домена, которые мне не нужны):
@TestFor(EmailService)
class EmailServiceTests {
void testEmailServiceWorks() {
def values = [test: 'test', test2: 'test2']
service.sendEmail(values)
}
}
Однако, когда я выполняю этот unit test, он не работает с этим исключением, когда пытается выполнить преобразование as JSON
:
org.apache.commons.lang.UnhandledException: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Неконвертируемый Объект класса: java.util.LinkedHashMap
Затем я повторно написал свой unit test, чтобы сделать следующее:
void testEmailServiceWorks() {
def value = [test: 'test', test2: 'test2']
def valueJson = value as JSON
}
И я получаю такое же исключение, когда он пытается выполнить преобразование as JSON
.
Кто-нибудь знает, почему я получаю это исключение, и как я могу это исправить?
Ответы
Ответ 1
Магия JSON создается при развертывании инфраструктуры домена.
Вам нужно либо сменить тест на интеграцию, либо высмеять asType.
def setUp(){
java.util.LinkedHashMap.metaClass.asType = { Class c ->
new grails.converters."$c"(delegate)
}
}
Rember, чтобы очистить себя после tearDown, вам не хотелось бы метапрограммировать утечки в вашем тестовом наборе.
def tearDown(){
java.util.LinkedHashMap.metaClass.asType = null
}
Изменить:
Если вы пришли из будущего, рассмотрите этот ответ: fooobar.com/questions/208528/...
Ответ 2
Даже если вы тестируете службу, вы можете применить аннотацию @TestMixin(ControllerUnitTestMixin)
к вашему тестовому классу, чтобы заставить Grails настроить конвертер JSON.
Ответ 3
вы можете инициализировать JSON в setUp(). Существуют различные маршаллеры, которые реализуют ObjectMarshaller, которые должны быть добавлены в преобразование ConverterConfiguration для преобразования JSON для работы.
http://grails.github.io/grails-doc/2.4.4/api/index.html?org/codehaus/groovy/grails/web/converters/marshaller/json/package-summary.html
пример:
DefaultConverterConfiguration<JSON> defaultConverterConfig = new DefaultConverterConfiguration<JSON>()
defaultConverterConfig.registerObjectMarshaller(new CollectionMarshaller())
defaultConverterConfig.registerObjectMarshaller(new MapMarshaller())
defaultConverterConfig.registerObjectMarshaller(new GenericJavaBeanMarshaller())
ConvertersConfigurationHolder.setTheadLocalConverterConfiguration(JSON.class, defaultConverterConfig);
Ответ 4
Я получал ту же ошибку при попытке unit test контроллера, который вызывает "render myMap as JSON". Мы используем Grails 1.3.7, и ни одно из других решений не работало для меня, не внося никаких других проблем. Модернизация Grails для нас в настоящее время не является альтернативой.
Моим решением было использовать JSONBuilder вместо "как JSON", например:
render(contentType: "application/json", {myMap})
См. http://docs.grails.org/latest/guide/theWebLayer.html#moreOnJSONBuilder
(Я понимаю, что это старый, но пришел сюда, чтобы найти решение, и, возможно, другие)