Saya menggunakan pythons mock.patch dan ingin mengubah nilai balik untuk setiap panggilan. Inilah peringatannya: fungsi yang ditambal tidak memiliki input, jadi saya tidak bisa mengubah nilai kembali berdasarkan input.
Ini kode saya untuk referensi.
def get_boolean_response():
response = io.prompt('y/n').lower()
while response not in ('y', 'n', 'yes', 'no'):
io.echo('Not a valid input. Try again'])
response = io.prompt('y/n').lower()
return response in ('y', 'yes')
Kode Tes saya:
@mock.patch('io')
def test_get_boolean_response(self, mock_io):
#setup
mock_io.prompt.return_value = ['x','y']
result = operations.get_boolean_response()
#test
self.assertTrue(result)
self.assertEqual(mock_io.prompt.call_count, 2)
io.prompt
hanyalah versi "input" platform independen (python 2 dan 3). Jadi pada akhirnya saya mencoba untuk mengolok-olok input pengguna. Saya telah mencoba menggunakan daftar untuk nilai pengembalian, tetapi itu tidak berhasil.
Anda dapat melihat bahwa jika nilai kembali adalah sesuatu yang tidak valid, saya hanya akan mendapatkan loop tak terbatas di sini. Jadi saya perlu cara untuk akhirnya mengubah nilai kembali, sehingga tes saya benar-benar selesai.
(cara lain yang mungkin untuk menjawab pertanyaan ini bisa dengan menjelaskan bagaimana saya bisa meniru input pengguna dalam unit-test)
Bukan dup dari pertanyaan ini terutama karena saya tidak memiliki kemampuan untuk memvariasikan input.
Salah satu komentar dari Jawaban atas pertanyaan ini sejalan, tetapi tidak ada jawaban / komentar yang diberikan.
sumber
response is not 'y' or 'n' or 'yes' or 'no'
dalam tidak melakukan apa yang Anda pikirkan. Lihat Bagaimana cara menguji satu variabel terhadap beberapa nilai? dan Anda tidak boleh menggunakanis
untuk membandingkan nilai string, gunakan==
untuk membandingkan nilai , bukan identitas objek.is
untuk membandingkan string literal. Jangan lakukan itu. Fakta bahwa ia berfungsi (kadang-kadang) hanyalah detail implementasi dalam CPython. Juga,response is not 'y' or 'n' or 'yes' or 'no'
mungkin tidak melakukan apa yang Anda pikirkan ...Jawaban:
Anda dapat menetapkan iterable ke
side_effect
, dan mock akan mengembalikan nilai berikutnya dalam urutan setiap kali dipanggil:Mengutip
Mock()
dokumentasi :Selain itu, tes tidak
response is not 'y' or 'n' or 'yes' or 'no'
akan berhasil; Anda bertanya apakah ekspresi itu benar, atau benar (selalu demikian, string yang tidak kosong selalu benar), dll. Berbagai ekspresi di kedua sisi operator independen . Lihat Bagaimana cara menguji satu variabel terhadap beberapa nilai?(response is not 'y')
'y'
or
Anda juga sebaiknya tidak menggunakan
is
untuk menguji terhadap string. Penerjemah CPython dapat menggunakan kembali objek string dalam keadaan tertentu , tetapi ini bukan perilaku yang harus Anda andalkan.Karena itu, gunakan:
sebagai gantinya; ini akan menggunakan tes kesetaraan (
==
) untuk menentukan apakahresponse
referensi string dengan konten (nilai) yang sama.Hal yang sama berlaku untuk
response == 'y' or 'yes'
; gunakanresponse in ('y', 'yes')
saja.sumber
mock
? Apakah ada cara untuk menggunakan tambalan dengan MagicMock seperti yang saya lakukan dengan mock standar?Mock
kelas stardard .m.side_effect = iter(['foo', 'bar', 'baz'])
).lambda
(fungsi), bukan aMagicMock
. Objek fungsi tidak dapat memiliki properti, jadiside_effect
atributnya harus dapat diulang. Anda seharusnya tidak menentukan metode seperti itu. Penggunaan yang lebih baikmock.patch.object(requests.Session, 'post')
; yang menghasilkan objek patcher yang secara otomatis menentukan spesifikasi pada metode, dan mendukungside_effect
dengan benar.StopIteration
dinaikkan. Anda dapat menggunakan iterator apa saja, sehingga Anda bisa menggunakannyaitertools.chain(['Foo'], itertools.repeat('Bar'))
untuk memproduksiFoo
sekali, lalu selamanya menghasilkanBar
.