2012-08-02 2 views
25

私は、HTTP呼び出しを行うことによって、サードパーティのサービスを使用して電子メールを送信Grailsのサービスを持っていますHibernateと私は必要としない、ドメイン全体の枠組み、):私はこのユニットテストを実行したとき、それはas JSON変換を行うことをしようとしたときコンバータを使用するGrailsサービスを単体テストする方法を教えてください。私は統合テストがスピンアップするので(このサービスをテストするためのユニットテストを書いた</p> <pre><code>class EmailService { def sendEmail(values) { def valueJson = values as JSON ... // does HTTP call to 3rd party service } } </code></pre> <p>:

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

はしかし、それはこの例外で失敗します

org.apache.commons.lang.UnhandledException:org.codehaus.groovy.grails.web.converters.exceptions.ConverterException:クラスのUnconvertableオブジェクト:java.util.LinkedHashMap

私はその後、私の再書いユニットテストは、ちょうど次の操作を実行します

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

そして、それはas JSON変換を行うことをしようとしたとき、私は同じ例外を取得します。

なぜこの例外が発生するのか誰にもわかりますが、どのように修正できますか?

答えて

9

JSONの魔法は、ドメインフレームワークがスピンアップしたときに作成されます。

テストをインテグレーションに変更するか、asTypeをモックする必要があります。

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

tearDownであなた自身の後をきれいにするには、テストスイートでリプログラミングをメタプログラミングする必要はありません。

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

編集: あなたが未来から来た場合は、この答えを考えてみます。https://stackoverflow.com/a/15485593/194932

+0

これはgrails 1.3.7でどのように動作しますか?私がこれを使うとき。予期しないトークンでランタイムエラーが発生します。新しいgrails.converters。 "$ {c}"(代理人) – allthenutsandbolts

+5

偉大な答え - 私は正しい方向に向かいました。 asTypeの構文がうまくいかなかったのに、 'c.newInstance(delegate)'が私のためにしました。 – Armand

+2

これは動作しません。正しい解決策は、 '@TestMixin(ControllerUnitTestMixin)'アノテーションを追加することです(後述の@ Stephenの答えを確認してください)。 – mathifonseca

4

ます(セットアップでJSONを初期化することができます)。 ObjectMarshallerを実装するさまざまなマーシャラーがいます。これらのマーシャラーは、JSON変換用のConverterConfigurationに追加する必要があります。

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); 
+0

リンクが無効です。 – Maladon

+1

@Maladonこれは、CodehausからのGrailsインフラストラクチャの移行のためです。試してみてください:http://grails.github.io/grails-doc/2.4.4/api/index.html?org/codehaus/groovy/grails/web/converters/marshaller/json/package-summary.html –

64

、あなたはJSONコンバータをセットアップするのGrailsを得るためにあなたのテストクラスに@TestMixin(ControllerUnitTestMixin)注釈を適用することができます。

+5

これはここで私のために働いた唯一の答えは – Alex

+0

@Alex - 私も;) –

+1

これは受け入れられた答えでなければなりません。だからきれいで、働く – Peter

1

「myMapをJSONとしてレンダリング」というコントローラを単体テストしようとすると、同じエラーが発生していました。私たちはGrails 1.3.7を使用しています。他の問題を導入することなく私のために働いた他のソリューションはありません。 Grailsのアップグレードは現時点では私たちのための代替手段ではありませんでした。

私のソリューションは、このように、「JSONとして」JSONBuilderを使う代わりにすることでした:

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

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

を参照してください(私はこれが古い実現が、ここでは解の探索中とそう来ました他人かもしれません)

関連する問題

 関連する問題