2011-12-20 24 views
28

Tôi đã có một cấu trúc sau:Làm thế nào để giả lập một hàm được định nghĩa trong một mô đun của một gói?

|-- 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() 

kết quả của python test.pyBar.

Làm thế nào để giả lập printBar để làm cho nó trở về Foo để printFoo sẽ in?

EDIT: Nếu không sửa đổi bất kỳ tập tin khác mà test.py

Trả lời

16

Tôi đoán bạn đang đi để thử chức năng returnBar, bạn muốn sử dụng patch decorator:

from mock import patch 

from foo import printFoo 

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

test_printFoo() 
23

Chỉ cần nhập các module bar trước module foo và chế nhạo nó:

from mock import Mock 

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

from foo import printFoo 

printFoo() 

Khi bạn đang nhập khẩu các returnBar trong foo.py, bạn đang ràng buộc giá trị của mô đun cho một biến được gọi là returnBar. Biến này là cục bộ, được đặt trong việc đóng chức năng printFoo() khi nhập foo - và không thể cập nhật các giá trị trong phần đóng bằng mã từ ngoài nó. Vì vậy, nó phải có giá trị mới (có nghĩa là, chức năng mô phỏng) trước khi nhập nhập foo.

EDIT: dung dịch giải pháp trước nhưng không mạnh vì nó phụ thuộc vào thứ tự nhập. Đó không phải là lý tưởng. Một giải pháp (đã xảy ra cho tôi sau khi một trong những đầu tiên) là để nhập khẩu các mô-đun bar trong foo.py thay vì chỉ nhập returnBar() chức năng:

from dirBar import bar 

def printFoo(): 
    print bar.returnBar() 

này sẽ làm việc vì returnBar() nay được lấy trực tiếp từ các module bar thay vì việc đóng cửa. Vì vậy, nếu tôi cập nhật mô-đun, chức năng mới sẽ được truy xuất.

+0

Có vấn đề là - Tôi đã có mã như vậy và không muốn thay đổi chúng. Sau khi thảo luận về freenode # python tôi đã quyết định tái cấu trúc tệp khác (ở đây foo.py) để nó sẽ tốt hơn và sạch hơn – zalun

+0

@zalun có liên kết đến cuộc thảo luận này không? Tôi tò mò về điều đó! – brandizzi

+0

không có ý tưởng - Tôi chỉ thấy rằng tôi không đăng nhập bất cứ điều gì ... – zalun

-3

Một cách khác để đối phó với những trường hợp đang sử dụng một số dependency injection.

Một cách dễ dàng để làm điều đó trong python là sử dụng ma thuật **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) 

này sẽ dẫn đến một kiểm chứng hơn mã (và tăng tính mô đun/khả năng sử dụng lại).

+2

toàn bộ ý tưởng là không sửa đổi bất cứ điều gì ngoại trừ test.py – zalun

4

Nơi tốt nhất tôi đã tìm thấy để giải quyết các vấn đề chế giễu là: http://alexmarandon.com/articles/python_mock_gotchas/

Bạn nên thử chức năng của các mô-đun được nhập khẩu bởi lớp dưới kiểm tra.

+3

liên kết trên câu trả lời được khuyến khích, tại sao bạn không tóm tắt những gì tài liệu của trang ở đây? – user22866

Các vấn đề liên quan