テスト自動化で使用するJavaアプリケーション用のGroovy Restクライアントを構築しています。私はもともとhttpBuilderでサービスを書いていましたが、レスポンスを解析する方法を理解できませんでした。非200の応答では、私は捕捉してメッセージに主張することができる例外があります。更新後、私はレスポンスを解析することができますが、非200レスポンスを取得すると、それをオブジェクトとして解析して、役に立たない 'missingProperty'例外をスローします。このドキュメントでは、response.parser <CONTENT_TYPE>, { config, fs ->...}
を使用して応答を解析する方法と、response.success{fs -> ...}
またはresponse.when(<CODE>){fs -> ...}
を使用してステータスコードを分岐する方法について説明しますが、成功のためにのみ解析する方法と、次のように私の現在のコードは次のとおりです。HttpBuilder-ngを使用して成功を解析したりエラーをスローするには
import groovyx.net.http.ChainedHttpConfig
import groovyx.net.http.FromServer
import groovyx.net.http.HttpBuilder
import groovyx.net.http.NativeHandlers
import static groovyx.net.http.ContentTypes.JSON
import static groovyx.net.http.NativeHandlers.Parsers.json
class CarClient {
private final HttpBuilder http
CarClient() {
http = HttpBuilder.configure {
request.uri = "localhost:8080"
request.encoder JSON, NativeHandlers.Encoders.&json
}
}
List<Car> getCars(make) {
http.get(List) {
request.uri.path = "/cars/make/${make}"
response.failure { fs ->
println("request failed: ${fs}")
}
response.parser JSON, { ChainedHttpConfig config, FromServer fs ->
json(config, fs).collect { x -> new Car(make: x."make", model: x."model") }
}
}
}
}
class Car {
def make
def model
}
その後、私のスポックテスト:
def "200 response should return list of cars"() {
when:
def result = client.getCars("honda")
then:
result.size == 3
result[0].make == "honda"
result[0].model == "accord"
}
def "404 responses should throw exception with 'not found'"() {
when:
client.getCars("ford")
then:
final Exception ex = thrown()
ex.message == "Not Found"
}
古いバージョンでは、最初のテストは失敗し、第二の試験は合格しました。新しいバージョンでは、最初のテストは合格し、2番目のテストは失敗します。私は実際にはrequest failed:...
メッセージも見たことがありません。私はちょうどgroovy.lang.MissingPropertyException
を得る。私がステップスルーすると、not found
の応答をCarオブジェクトとしてロードしようとしているのがわかります。
ボーナス:なぜドキュメントのようにGroovyキャストの代わりに明示的なプロパティマッピングを使用する必要がありますか?
json(config, fs).collect { x -> x as Car }
更新 - これは私の実際の情報源ではありません。私は完全に制御していない、WAS上で動作する独自の内部APIにぶつかっています。私はAPIのビジネスロジックを書いていますが、WASと私がアクセスできない独自のライブラリを使用してレスポンスをマーシャル/アンマーシャリングしています。無名/私の仕事を保護するために名前が変更されました。これらは私が最初のポストから試した回避策です: これは200以外の応答で失敗ブロックを正しくトリガーしますが、構文解析はIO - stream closed
エラーで失敗します。また、私が失敗ブロックにスローする例外はRuntimeExceptionにラップされ、情報にアクセスできなくなります。私は、ドキュメントで提案されているようなトランスポート例外でラップしようとしましたが、それが得られるまでにはまだRuntimeExceptionです。
List<Car> getCars(make) {
http.get(List) {
request.uri.path = "/cars/make/${make}"
response.failure { fs ->
println("request failed: ${fs}")
throw new AutomationException("$fs.statusCode : $fs.message")
}
response.success { FromServer fs ->
new JsonSlurper().parse(new InputStreamReader(fs.getInputStream, fs.getCharset())).collect { x -> new Car(make: x."make", model: x."model") }
}
}
}
}
これは、エントリがある200個の応答で正しく解析されますが、エントリのない200個もプロパティ例外が見つからなくなってしまいます。以前のimplと同様に、AutomationExceptionはラップされているため、有用ではありません。ボーナスについて
List<Car> getCars(make) {
http.get(List) {
request.uri.path = "/cars/make/${make}"
response.parser JSON, { ChainedHttpConfig config, FromServer fs ->
if (fs.statusCode == 200) {
json(config, fs).collect { x -> new Car(make: x."make", model: x."model") }
} else {
throw new AutomationException("$fs.statusCode : $fs.message")
}
}
}
}
、私は次のようれたガイドは、Carオブジェクトにjson(config, fs)
出力の暗黙のキャストを示しました。私は明示的に新しいオブジェクトの小道具を設定する必要があります。大したことではありませんが、私は別のものを間違って設定したかどうか疑問に思います。
@ thejames42これで問題は解決しますか? – cjstehno
残念ながら。問題は、応答がいつもコンテンツタイプ 'application/json'で返ってくるということだと思うので、パーサは常に起動されます。私はパーサーを削除して成功クローズで '新しいJSONSlurper(... fs.getIntputStream)を呼び出そうとしましたが、 'stream closed'エラーがスローされます。私がこれまでに持っているベストは、ネイティブハンドラを呼び出す前にパーサークロージャでtry catchを追加していますが、例外処理は混乱しています。テストをビルドしようとしていますが、それはサイドプロジェクトなので、作業する時間はそれほどありません。 – thejames42