Câu hỏi Hàm python Mocking dựa trên các đối số đầu vào


Chúng tôi đã sử dụng Chế nhạo cho python trong một thời gian.

Bây giờ, chúng ta có một tình huống mà chúng ta muốn giả lập một hàm

def foo(self, my_param):
    #do something here, assign something to my_result
    return my_result

Thông thường, cách để giả lập điều này sẽ là (giả sử foo là một phần của một đối tượng)

self.foo = MagicMock(return_value="mocked!")

Thậm chí, nếu tôi gọi foo () một vài lần tôi có thể sử dụng

self.foo = MagicMock(side_effect=["mocked once", "mocked twice!"])

Bây giờ, tôi đang đối mặt với một tình huống mà tôi muốn trả về một giá trị cố định khi tham số đầu vào có một giá trị cụ thể. Vì vậy, nếu giả sử "my_param" bằng "cái gì đó" thì tôi muốn trả về "my_cool_mock"

Điều này dường như có sẵn trên mockito cho python

when(dummy).foo("something").thenReturn("my_cool_mock")

Tôi đã tìm kiếm cách để đạt được điều tương tự với Mock không thành công?

Bất kỳ ý tưởng?


76
2018-04-23 05:59


gốc


Có thể là câu trả lời này sẽ giúp - stackoverflow.com/a/7665754/234606 - naiquevin
@naiquevin Điều này hoàn toàn giải quyết vấn đề người bạn đời, cảm ơn! - Juan Antonio Gomez Moriano
Tôi không biết bạn có thể sử dụng Mocktio với Python, +1 cho điều đó! - Ben


Các câu trả lời:


Nếu side_effect là một hàm thì bất cứ hàm nào trả về là   những gì các cuộc gọi đến sự trở lại giả. Các side_effect chức năng được gọi với   các đối số giống như giả lập. Điều này cho phép bạn thay đổi lợi nhuận   giá trị của cuộc gọi tự động, dựa trên đầu vào:

>>> def side_effect(value):
...     return value + 1
...
>>> m = MagicMock(side_effect=side_effect)
>>> m(1)
2
>>> m(2)
3
>>> m.mock_calls
[call(1), call(2)]

http://www.voidspace.org.uk/python/mock/mock.html#calling


101
2018-04-23 06:05



Chỉ để làm cho câu trả lời dễ dàng hơn, bạn có thể đổi tên hàm side_effect thành một thứ khác không? (Tôi biết, tôi biết, nó là khá đơn giản, nhưng cải thiện khả năng đọc thực tế là tên chức năng và tên param là khác nhau :) - Juan Antonio Gomez Moriano
@JuanAntonioGomezMoriano Tôi có thể, nhưng trong trường hợp này tôi chỉ trích dẫn trực tiếp tài liệu, vì vậy tôi hơi băn khoăn khi chỉnh sửa báo giá nếu nó không bị hỏng cụ thể. - Amber
và chỉ để trở thành pedantic tất cả những năm sau đó, nhưng side effect là thuật ngữ chính xác: en.wikipedia.org/wiki/Side_effect_(computer_science) - lsh
@ Tôi không phàn nàn về tên của CallableMixin.side_effect, nhưng hàm riêng biệt được định nghĩa trong ví dụ có cùng tên. - OrangeDog


Như được chỉ ra tại Đối tượng Python Mock với phương thức được gọi nhiều lần

Một giải pháp là viết side_effect của riêng tôi

def my_side_effect(*args, **kwargs):
    if args[0] == 42:
        return "Called with 42"
    elif args[0] == 43:
        return "Called with 43"
    elif kwarg['foo'] == 7:
        return "Foo is seven"

mockobj.mockmethod.side_effect = my_side_effect

Điều đó không phải là lừa


15
2018-04-23 06:19



Điều này làm cho nó rõ ràng hơn cho tôi hơn câu trả lời đã chọn, vì vậy cảm ơn bạn đã trả lời câu hỏi của riêng bạn :) - Luca Bezerra


Tác dụng phụ có chức năng (cũng có thể là một hàm lambda), vì vậy đối với các trường hợp đơn giản, bạn có thể sử dụng:

m = MagicMock(side_effect=(lambda x: x+1))

6
2017-08-30 05:19





Chỉ để thể hiện một cách khác để làm điều đó:

def mock_isdir(path):
    return path in ['/var/log', '/var/log/apache2', '/var/log/tomcat']

with mock.patch('os.path.isdir') as os_path_isdir:
    os_path_isdir.side_effect = mock_isdir

0
2017-12-08 21:08





Tôi biết câu hỏi khá cũ của nó, có thể giúp cải thiện bằng cách sử dụng lệnh trăn lamdba

self.some_service.foo.side_effect = lambda *args:"Called with 42" \
            if args[0] == 42 \
            else "Called with 42" if args[0] == 43 \
            else "Called with 43" if args[0] == 43 \
            else "Called with 45" if args[0] == 45 \
            else "Called with 49" if args[0] == 49 else None

-1
2017-07-02 08:04