30

HTTP呼び出しを行うことでサードパーティのサービスを使用して電子メールを送信するGrailsサービスがあります。

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

このサービスをテストするための単体テストを作成しました(統合テストはHibernateとドメインフレームワーク全体を起動するため、必要ありません):

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

ただし、この単体テストを実行すると、as JSON変換を実行しようとすると、次の例外で失敗します。

org.apache.commons.lang.UnhandledException:org.codehaus.groovy.grails.web.converters.exceptions.ConverterException:クラスの変換不可能なオブジェクト:java.util.LinkedHashMap

次に、単体テストを書き直して、次のことを実行します。

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

as JSONそして、変換しようとすると同じ例外が発生します。

なぜこの例外が発生するのか、どうすれば修正できるのか、誰か知っていますか?

4

6 に答える 6

71

サービスをテストしている場合でも、@TestMixin(ControllerUnitTestMixin)テストクラスにアノテーションを適用して、GrailsにJSONコンバーターをセットアップさせることができます。

于 2013-03-18T19:49:25.083 に答える
10

as JSONマジックは、ドメインフレームワークが起動したときに作成されます。

テストを統合テストに変更するか、asTypeをモックする必要があります。

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

ティアダウンで自分の後でクリーンアップするために、テストスイートでメタプログラミングリークが発生することは望ましくありません。

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

編集:あなたが未来から来た場合は、この答えを検討してください:https ://stackoverflow.com/a/15485593/194932

于 2012-08-02T21:45:06.367 に答える
7

Grails3.3.xgrails-test-mixinsプラグインは非推奨になりました。@移行ガイドを参照してください。

この問題については、 Grails TestingSupportFrameworkGrailsWebUnitTestから提供されているものを実装する必要があります。

于 2018-07-12T13:21:59.513 に答える
5

setUp()で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);
于 2012-08-05T18:20:18.937 に答える
2

GrailsWebUnitTest私はこれに遭遇したばかりで、ここでの別の回答で推奨されているように実装したくありませんでした。サービステストを「純粋」に保ち、可能な限り無駄を省きたいです。私はこれをすることになった:

void setupSpec() {
    defineBeans(new ConvertersGrailsPlugin())
}

void cleanupSpec() {
    ConvertersConfigurationHolder.clear()
}

GrailsWebUnitTestこれは、 (およびを介しWebSetupSpecInterceptorて)実装するときに内部で発生する方法ですWebCleanupSpecInterceptor


とは言うものの、コンバーターは、主にコントローラーからさまざまな形式のデータを透過的に返すことを容易にするために、Web層で使用することを目的としているようです。テストしているサービスがそもそもコンバーターを必要とする理由を検討する価値があります。

たとえば、私の場合、誰かがJSONコンバーターを使用してデータを文字列にシリアル化し、データベースの単一のフィールドに格納できるようにしました。それはコンバーターの適切なユーザーのようには思えないので、私はそれがどのように行われるかを変更することを計画しています。サービステストでコンバーターを利用できるようにすることは、リファクタリングする前にテストカバレッジを改善できるようにするための一時的なソリューションです。

于 2020-03-27T16:15:50.900 に答える
1

「rendermyMapasJSON」を呼び出すコントローラーを単体テストしようとしたときに同じエラーが発生していました。Grails 1.3.7を使用していますが、他の問題を発生させることなく、他のソリューションはどれも機能しませんでした。現時点では、Grailsのアップグレードは私たちの代替手段ではありませんでした。

私の解決策は、次のように「asJSON」の代わりにJSONBuilderを使用することでした。

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

http://docs.grails.org/latest/guide/theWebLayer.html#moreOnJSONBuilderを参照してください

(私はこれが古いことを理解していますが、解決策を探してここに来ました、そして他の人もそうかもしれません)

于 2016-07-15T10:40:25.090 に答える