2012-08-02 12 views
25

Mam usług Grails, który wysyła e-maile za pomocą usługi 3rd partii wykonując połączenia http:W jaki sposób mogę przetestować usługę Grails korzystającą z konwertera?

class EmailService { 
    def sendEmail(values) { 
     def valueJson = values as JSON 
     ... // does HTTP call to 3rd party service 
    } 
} 

Pisałem test jednostki przetestować tę usługę (bo test integracja obraca się hibernacji i cała struktura domeny, które nie muszę):

@TestFor(EmailService) 
class EmailServiceTests { 
    void testEmailServiceWorks() { 
     def values = [test: 'test', test2: 'test2'] 
     service.sendEmail(values) 
    } 
} 

jednak, kiedy wykonać test jednostki, nie jest on z tym wyjątkiem, gdy próbuje zrobić konwersję as JSON:

org.apache.commons.lang.UnhandledException: org.codehaus.groovy.grails.web.converters.exceptions.ConverterException: Unconvertable Obiekt klasy: java.util.LinkedHashMap

I ponownie pisałam badanej jednostki po prostu wykonaj następujące czynności:

void testEmailServiceWorks() { 
    def value = [test: 'test', test2: 'test2'] 
    def valueJson = value as JSON 
} 

I uzyskać ten sam wyjątek, gdy próbuje zrobić konwersję as JSON.

Czy ktoś wie, dlaczego otrzymuję ten wyjątek i jak mogę to naprawić?

Odpowiedz

9

Magia JSON jest tworzona, gdy struktura domeny obraca się.

Musisz zmienić test na integrujący lub kpić z asType.

def setUp(){ 
    java.util.LinkedHashMap.metaClass.asType = { Class c -> 
     new grails.converters."$c"(delegate) 
    } 
} 

Sprzątanie po sobie w łzy, nie chciałbyś przeciekać metaprogramowania w zestawie testowym.

def tearDown(){ 
    java.util.LinkedHashMap.metaClass.asType = null 
} 

Edit: Jeśli pochodzą z przyszłości, należy rozważyć tę odpowiedź: https://stackoverflow.com/a/15485593/194932

+0

Jak to będzie działać w grails 1.3.7. Kiedy używam tego. Otrzymuję komunikat o błędzie wykonywania na nieoczekiwanym tokenie:. nowe grails.converters. "$ {c}" (delegat) – allthenutsandbolts

+5

Świetna odpowiedź - ustaw mnie we właściwym kierunku. Podana składnia dla asType nie działała, ale 'c.newInstance (delegate)' zrobił dla mnie. – Armand

+2

To nie działa, poprawnym rozwiązaniem jest dodanie adnotacji '@TestMixin (ControllerUnitTestMixin)' (sprawdź odpowiedź @ Stephena poniżej). – mathifonseca

4

można zainicjować JSON w konfiguracji(). Istnieje wiele koordynatorów, które implementują program ObjectMarshaller, który należy dodać do konwertera Konwerter dla JSON, aby działał.

http://grails.github.io/grails-doc/2.4.4/api/index.html?org/codehaus/groovy/grails/web/converters/marshaller/json/package-summary.html

przykład:

DefaultConverterConfiguration<JSON> defaultConverterConfig = new DefaultConverterConfiguration<JSON>() 
defaultConverterConfig.registerObjectMarshaller(new CollectionMarshaller()) 
defaultConverterConfig.registerObjectMarshaller(new MapMarshaller()) 
defaultConverterConfig.registerObjectMarshaller(new GenericJavaBeanMarshaller()) 

ConvertersConfigurationHolder.setTheadLocalConverterConfiguration(JSON.class, defaultConverterConfig); 
+0

Link nie działa. – Maladon

+1

@Maladon To dlatego, że infrastruktura Grails przenosi się z Codehaus. Wypróbuj to: http://grails.github.io/grails-doc/2.4.4/api/index.html?org/codehaus/groovy/grails/web/converters/marshaller/json/package-summary.html –

64

Nawet jeśli testuje usługę, można zastosować @TestMixin(ControllerUnitTestMixin) adnotacji do klasy testowej, aby uzyskać Grails założyć konwerter JSON.

+5

this jest jedyną odpowiedzią, która zadziałała dla mnie na 3 tutaj – Alex

+0

@Alex - ja też;) –

+1

To powinna być zaakceptowana odpowiedź. Tak czyste i działa – Peter

1

Wystąpił ten sam błąd podczas próby przetestowania kontrolera, który wywołuje "render myMap jako JSON". Używamy Grails 1.3.7 i żadne z innych rozwiązań nie działa dla mnie bez wprowadzania innych problemów. Aktualizacja Grails nie była w tej chwili dla nas alternatywą.

Moje rozwiązanie było użyć JSONBuilder zamiast „jak JSON”, na przykład:

render(contentType: "application/json", {myMap}) 

Zobacz http://docs.grails.org/latest/guide/theWebLayer.html#moreOnJSONBuilder

(zdaję sobie sprawę, to jest stary, ale przyszedł tu w poszukiwaniu rozwiązania i tak może inni)