Python trả về đối tượng MagicMock thay vì return_value


87

Tôi có một tệp python a.pychứa hai lớp AB.

class A(object):
    def method_a(self):
        return "Class A method a"

class B(object):
    def method_b(self):
        a = A()
        print a.method_a()

Tôi muốn nổi nhất method_btrong lớp Bbằng cách chế giễu A. Đây là nội dung của tệp testa.pycho mục đích này:

import unittest
import mock
import a


class TestB(unittest.TestCase):

    @mock.patch('a.A')
    def test_method_b(self, mock_a):
        mock_a.method_a.return_value = 'Mocked A'
        b = a.B()
        b.method_b()


if __name__ == '__main__':
    unittest.main()

Tôi mong đợi để có được Mocked Ađầu ra. Nhưng những gì tôi nhận được là:

<MagicMock name='A().method_a()' id='4326621392'>

Tôi đang làm sai ở đâu?


1
Khi kiểm tra, A()trả về return_valuefrom mock_A(một thông thường MagicMock, vì bạn chưa chỉ định bất kỳ điều gì khác), không phải là một phiên bản của lớp A. Bạn cần phải đặt đó return_valuelà một cái gì đó đã được xác định method_a.
jonrsharpe

3
mock_a.method_a.return_value = 'chế nhạo A' => mock_a () method_a.return_value = 'chế nhạo A' nên được tốt hơn :).
Ali nói OMAR

@AliSAIDOMAR là chính xác, đó là giá trị trả về từ việc gọi mock_aphải có phương thức, không phải mock_achính nó.
jonrsharpe

1
@jonrsharpe. Cảm ơn lời giải thích của bạn. Tôi chỉ cố gắng. Cả hai mock_a().method_a.return_value = 'Mocked A'mock_a.return_value.method_a.return_value = 'Mocked A'đã hoạt động. Cảm ơn rất nhiều ý kiến ​​của bạn. Bạn vui lòng tiếp tục và đặt nó như một câu trả lời?
Mehdi Jafarnia Jahromi

@MehdiJafarniaJahromi cảm ơn rất nhiều!
Niakros

Câu trả lời:


97

Khi bạn @mock.patch('a.A'), bạn đang thay thế lớp Atrong mã được kiểm tra bằng mock_a.

Trong B.method_bbạn sau đó thiết lập a = A(), mà bây giờ a = mock_a()- tức areturn_valuecủa mock_a. Vì bạn chưa chỉ định giá trị này, nó là một giá trị thường xuyên MagicMock; điều này cũng không được định cấu hình, vì vậy bạn sẽ nhận được phản hồi mặc định (nhưng khác MagicMock) khi gọi các phương thức trên đó.

Thay vào đó, bạn muốn cấu hình các return_valuecủamock_a để có phương pháp thích hợp, mà bạn có thể làm là một trong hai:

mock_a().method_a.return_value = 'Mocked A' 
    # ^ note parentheses

hoặc, có lẽ rõ ràng hơn:

mock_a.return_value.method_a.return_value = 'Mocked A'

Mã của bạn sẽ hoạt động trong trường hợp này a = A(gán lớp chứ không phải tạo một thể hiện), vì sau đó a.method_a()sẽ kích hoạt phương thức giả của bạn.


4
Tuyệt vời. Bạn đã làm nên ngày của tôi.
Vishal

Xin chào @jonrsharpe, tôi đang sử dụng khung dữ liệu gấu trúc với df.columns để kiểm tra điều kiện if của mình . Nó không sử dụng dấu ngoặc đơn (tức là nó không thể gọi được). Tôi phải làm gì để trả về một danh sách trong trường hợp đó. Cảm ơn!
imsrgadich

@imsrgadich bạn có cần một mô hình cho điều đó không? Chỉ cần xây dựng khung dữ liệu thích hợp, coi nó như một giá trị thử nghiệm.
jonrsharpe

@jonrsharpe vâng, tôi có thể làm điều đó nhưng tôi cũng đang thực hiện df.drop trong phương thức được gọi của mình mà tôi cần xác nhận và qua đó tôi sẽ không trả lại khung dữ liệu từ phương thức được gọi. Điều đó tạo ra một vấn đề. Tôi đã tìm thấy một cách sử dụng mock_data.configure_mock(columns='my_column')để giải quyết nó. Cảm ơn vì lời đáp sâu sắc. (ref: bradmontgomery.net/blog/how-world-do-you-mock-name-attribute )
imsrgadich

Điều này dường như không hoạt động khi bạn mô phỏng hai mô hình SQLAlchemy trong cùng một bài kiểm tra. Cái đầu tiên hoạt động tốt, nhưng cái thứ hai sẽ trả về MagicMock bất kể bạn xác định cái gì.
Juha Untinen
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.