Saya memiliki kode berikut di controller saya:
format.json { render :json => {
:flashcard => @flashcard,
:lesson => @lesson,
:success => true
}
Dalam tes pengontrol RSpec saya, saya ingin memverifikasi bahwa skenario tertentu tidak menerima respons json sukses jadi saya memiliki baris berikut:
controller.should_receive(:render).with(hash_including(:success => true))
Meskipun ketika saya menjalankan tes saya, saya mendapatkan kesalahan berikut:
Failure/Error: controller.should_receive(:render).with(hash_including(:success => false))
(#<AnnoController:0x00000002de0560>).render(hash_including(:success=>false))
expected: 1 time
received: 0 times
Apakah saya salah mengecek respons?
ruby-on-rails
json
rspec
Mendesis
sumber
sumber
post :create
dengan hash parameter yang valid.post :create, :format => :json
{"a":"1","b":"2"}
dan{"b":"2","a":"1"}
bukan string yang sama yang mencatat objek yang sama. Anda tidak harus membandingkan string tetapi objek, lakukanJSON.parse('{"a":"1","b":"2"}').should == {"a" => "1", "b" => "2"}
saja.Anda dapat menguraikan badan respons seperti ini:
Kemudian Anda dapat membuat pernyataan terhadap konten yang diurai tersebut.
sumber
b = JSON.parse(response.body, symoblize_names: true)
sehingga Anda dapat mengaksesnya menggunakan simbol-simbol seperti:b[:foo]
Membangun dari jawaban Kevin Trowbridge
sumber
Mime::JSON
saja'application/json'
?Mime::JSON.to_s
Ada juga permata json_spec , yang patut dilihat
https://github.com/collectiveidea/json_spec
sumber
Sederhana dan mudah untuk melakukannya.
sumber
Anda juga dapat mendefinisikan fungsi pembantu di dalam
spec/support/
dan gunakan
json_body
kapan pun Anda perlu mengakses respons JSON.Misalnya, di dalam spesifikasi permintaan Anda, Anda dapat menggunakannya secara langsung
sumber
Pendekatan lain untuk menguji hanya untuk respons JSON (bukan berarti konten di dalamnya mengandung nilai yang diharapkan), adalah untuk menguraikan respons menggunakan ActiveSupport:
Jika responsnya tidak parsable, JSON pengecualian akan dilemparkan dan tes akan gagal.
sumber
Anda bisa melihat ke
'Content-Type'
header untuk melihat apakah itu benar?sumber
render :json => object
, saya percaya Rails mengembalikan header Tipe-Konten dari 'application / json'.response.header['Content-Type'].should match /json/
Saat menggunakan Rails 5 (saat ini masih dalam versi beta), ada metode baru,
parsed_body
pada respons tes, yang akan mengembalikan respons yang diuraikan seperti apa permintaan terakhir dikodekan.Komit di GitHub: https://github.com/rails/rails/commit/eee3534b
sumber
#parsed_body
. Belum didokumentasikan, tetapi setidaknya format JSON berfungsi. Perhatikan bahwa kunci masih berupa string (bukan simbol), jadi orang mungkin menemukan salah satu#deep_symbolize_keys
atau#with_indifferent_access
berguna (saya suka yang terakhir).Jika Anda ingin memanfaatkan hash diff yang disediakan oleh Rspec, lebih baik mengurai tubuh dan membandingkannya dengan hash. Cara paling sederhana yang saya temukan:
sumber
Solusi perbandingan JSON
Menghasilkan Diff yang bersih namun berpotensi besar:
Contoh output konsol dari data nyata:
(Terima kasih untuk komentar oleh @floatingrock)
Solusi perbandingan string
Jika Anda menginginkan solusi berbalut besi, Anda harus menghindari penggunaan parser yang dapat memperkenalkan kesetaraan positif palsu; bandingkan tubuh respons terhadap string. misalnya:
Tetapi solusi kedua ini kurang ramah secara visual karena menggunakan JSON berseri yang akan mencakup banyak tanda kutip yang lolos.
Solusi pencocokan khusus
Saya cenderung menulis sendiri pencocokan kustom yang melakukan pekerjaan yang jauh lebih baik untuk menentukan dengan tepat di mana slot rekursif jalur JSON berbeda. Tambahkan berikut ini ke makro rspec Anda:
Contoh penggunaan 1:
Contoh penggunaan 2:
Contoh output:
Contoh output lain untuk menunjukkan ketidakcocokan jauh di dalam array bersarang:
Seperti yang Anda lihat, output memberitahu Anda PERSIS di mana untuk memperbaiki JSON yang Anda harapkan.
sumber
Saya menemukan pencocokan pelanggan di sini: https://raw.github.com/gist/917903/92d7101f643e07896659f84609c117c4c279dfad/have_content_type.rb
Letakkan di spec / support / matchers / have_content_type.rb dan pastikan untuk memuat hal-hal dari dukungan dengan sesuatu seperti ini di dalam Anda spec / spec_helper.rb
Ini kode itu sendiri, kalau-kalau kode itu hilang dari tautan yang diberikan.
sumber
Banyak jawaban di atas agak ketinggalan zaman, jadi ini adalah ringkasan cepat untuk versi RSpec yang lebih baru (3,8+). Solusi ini tidak menimbulkan peringatan dari rubocop-rspec dan sejalan dengan praktik terbaik rspec :
Respons JSON yang berhasil diidentifikasi oleh dua hal:
application/json
Dengan asumsi bahwa objek respons adalah subjek uji anonim, kedua kondisi di atas dapat divalidasi menggunakan pencocokan bawaan Rspec:
Jika Anda siap menyebutkan nama subjek, maka tes di atas dapat disederhanakan lebih lanjut:
sumber