Pertanyaan Bagaimana cara mengejek fungsi yang didefinisikan dalam modul paket?


Saya punya struktur berikut:

|-- dirBar
|   |-- __init__.py
|   |-- bar.py
|-- foo.py
`-- test.py

bar.py

def returnBar():
    return 'Bar'

foo.py

from dirBar.bar import returnBar

def printFoo():
    print returnBar()

test.py

from mock import Mock

from foo import printFoo
from dirBar import bar

bar.returnBar = Mock(return_value='Foo')

printFoo()

hasil dari python test.py aku s Bar.

Bagaimana cara mengejeknya printBar untuk membuatnya kembali Foo maka printFoo akan mencetaknya?

EDIT: Tanpa memodifikasi file lain itu test.py


32
2017-12-20 12:50


asal


Jawaban:


Saya menduga Anda akan mengejek fungsi returnBar, Anda ingin menggunakannya patch penghias:

from mock import patch

from foo import printFoo

@patch('foo.returnBar')
def test_printFoo(mockBar):
    mockBar.return_value = 'Foo'
    printFoo()

test_printFoo()

20
2017-12-20 13:01



Cukup impor bar modul sebelum foo modul dan mengejeknya:

from mock import Mock

from dirBar import bar
bar.returnBar = Mock(return_value='Foo')

from foo import printFoo

printFoo()

Saat Anda mengimpor returnBar di foo.py, Anda mengikat nilai modul ke variabel yang disebut returnBar. Variabel ini bersifat lokal sehingga dimasukkan ke dalam penutupan printFoo() berfungsi saat foo diimpor - dan nilai-nilai dalam penutupan tidak dapat diperbarui oleh kode dari outiside itu. Jadi, seharusnya memiliki nilai baru (yaitu fungsi mengejek) sebelum pengimporan foo.

EDIT: solusi sebelumnya tetapi tidak kuat karena tergantung pada pemesanan impor. Itu tidak terlalu ideal. Solusi lain (yang terjadi pada saya setelah yang pertama) adalah mengimpor bar modul dalam foo.py alih-alih hanya mengimpor returnBar() fungsi:

from dirBar import bar

def printFoo():
    print bar.returnBar()

Ini akan berhasil karena returnBar() sekarang diambil langsung dari bar modul bukannya penutupan. Jadi jika saya memperbarui modul, fungsi baru akan diambil.


24
2017-12-20 12:56



Tempat terbaik yang saya temukan untuk menyelesaikan masalah mengejek adalah: http://alexmarandon.com/articles/python_mock_gotchas/ 

Anda harus mengejek fungsi modul yang diimpor oleh kelas yang sedang diuji.


4
2018-03-12 15:24



Cara lain untuk menangani kasus tersebut adalah dengan menggunakan beberapa suntikan ketergantungan.

Cara mudah untuk melakukannya dengan python adalah menggunakan sihir **kwargs :

foo.py

from dirBar.bar import returnBar

def printFoo(**kwargs):
    real_returnBar = kwargs.get("returnBar", returnBar)
    print real_returnBar()

test.py

from mock import Mock

from foo import printFoo
from dirBar import bar

mocked_returnBar = Mock(return_value='Foo')

printFoo(returnBar=mocked_returnBar)

ini akan mengarah ke kode yang lebih dapat diuji (dan meningkatkan modularitas / usabilitas).


-3
2017-12-20 13:03