Python ส่งคืนวัตถุ MagicMock แทน return_value


93

ฉันมีไฟล์ python a.pyซึ่งมีสองคลาสAและB.

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

ผมอยากจะ UnitTest method_bในชั้นเรียนโดยการเยาะเย้ยB Aนี่คือเนื้อหาของไฟล์testa.pyสำหรับวัตถุประสงค์นี้:

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

ฉันคาดว่าจะได้รับMocked Aในผลลัพธ์ แต่สิ่งที่ฉันได้รับคือ:

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

ฉันทำผิดตรงไหน?


1
เมื่อทดสอบA()ส่งกลับreturn_valueจากmock_A(ปกติMagicMockในขณะที่คุณยังไม่ได้ระบุสิ่งอื่น) Aซึ่งไม่ได้เป็นตัวอย่างของการเรียน คุณจะต้องตั้งว่าจะเป็นสิ่งที่ได้กำหนดไว้return_value method_a
jonrsharpe

3
mock_a.method_a.return_value = 'Mocked A' => mock_a (). method_a.return_value = 'Mocked A' น่าจะดีกว่า :)
Ali SAID OMAR

@AliSAIDOMAR ถูกต้องแม่นยำเป็นค่าส่งคืนจากการโทรmock_aที่ควรมีวิธีการไม่ใช่mock_aตัวเอง
jonrsharpe

1
@jonrsharpe. ขอบคุณสำหรับคำอธิบาย ฉันเพิ่งพยายาม ทั้งสองmock_a().method_a.return_value = 'Mocked A'และmock_a.return_value.method_a.return_value = 'Mocked A'ทำงาน ขอบคุณมากสำหรับความคิดเห็นของคุณ ช่วยตอบให้หน่อยได้ไหมคะ
Mehdi Jafarnia Jahromi

@MehdiJafarniaJahromi ขอบคุณมาก!
Niakros

คำตอบ:


104

เมื่อคุณ@mock.patch('a.A')คุณจะเปลี่ยนชั้นในรหัสภายใต้การทดสอบด้วยAmock_a

ในB.method_bที่คุณตั้งไว้แล้วa = A()ซึ่งขณะนี้a = mock_a()- คือaเป็นของreturn_value mock_aในขณะที่คุณยังไม่ได้ระบุค่านี้ก็เป็นปกติMagicMock; สิ่งนี้ไม่ได้กำหนดค่าไว้ดังนั้นคุณจะได้รับการตอบสนองเริ่มต้น (อีกครั้งMagicMock) เมื่อเรียกวิธีการ

แต่คุณต้องการกำหนดค่าของที่จะมีวิธีการที่เหมาะสมที่คุณสามารถทำตามอย่างใดอย่างหนึ่งreturn_valuemock_a

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

หรืออาจจะชัดเจนกว่านี้:

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

รหัสของคุณจะใช้งานได้ในกรณีนี้a = A(การกำหนดคลาสไม่ใช่การสร้างอินสแตนซ์) เนื่องจากa.method_a()จะทำให้เกิดวิธีการจำลองของคุณ


4
น่ากลัว คุณทำให้วันของฉัน
Vishal

สวัสดี @jonrsharpe ฉันใช้แพนด้าดาต้าเฟรมกับdf.columnsเพื่อตรวจสอบเงื่อนไขifของฉัน มันไม่ใช้วงเล็บ (กล่าวคือไม่สามารถเรียกได้) ฉันจะทำอย่างไรเพื่อส่งคืนรายการในกรณีนั้น ขอบคุณ!
imsrgadich

@imsrgadich คุณต้องการล้อเลียนหรือไม่? เพียงแค่สร้างดาต้าเฟรมที่เหมาะสมถือว่าเป็นค่าทดสอบ
jonrsharpe

@jonrsharpe ใช่ฉันทำได้ แต่ฉันยังแสดง df.drop ในวิธีการที่ฉันเรียกซึ่งฉันต้องยืนยันว่าฉันไม่ได้ส่งคืนดาต้าเฟรมกลับจากเมธอดที่เรียก นั่นสร้างปัญหา ฉันพบวิธีที่ใช้mock_data.configure_mock(columns='my_column')แก้ปัญหาได้ ขอบคุณสำหรับการตอบกลับ (อ้างอิง: bradmontgomery.net/blog/how-world-do-you-mock-name-attribute )
imsrgadich

ดูเหมือนจะไม่ได้ผลเมื่อคุณจำลอง SQLAlchemy สองรุ่นในการทดสอบเดียวกัน อันแรกใช้งานได้ แต่อันที่สองจะส่งคืน MagicMock โดยไม่คำนึงถึงสิ่งที่คุณกำหนด
Juha Untinen
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.