มัณฑนากร mock.patch: ขาดอาร์กิวเมนต์ตำแหน่งที่จำเป็น 1 รายการ: 'ตนเอง'

ฉันกำลังพยายามแก้ไขตัวแปรในโมดูล settings ระหว่างการทดสอบวิธีรัน:

from unittest import mock

class Test(...):

    @mock.patch('settings.TARGET_SCORES_PER_SECTION', True)
    def test_register_user(self):

ฉันได้รับข้อผิดพลาดนี้:

ERROR: tests.test_user.transplant_class.<locals>.C (test_register_user)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/local/Cellar/python/3.6.5_1/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/mock.py", line 1179, in patched
    return func(*args, **keywargs)
TypeError: test_register_user() missing 1 required positional argument: 'self'

ฉันลองใช้วิธีอื่นแล้ว ไม่พบวิธีแก้ไข

ผมทำอะไรผิดหรือเปล่า?

เวอร์ชันนี้ใช้งานได้ดี:

    def test_register_user(self):
        with mock.patch('settings.TARGET_SCORES_PER_SECTION', True):
            self._test_register_user()

    def _test_register_user(self):

และฉันหวังว่าจะใช้เป็น มัณฑนากรก็จะทำงานในลักษณะเดียวกัน


person warvariuc    schedule 17.04.2019    source แหล่งที่มา
comment
อย่าลืมนำเข้า settings และเพิ่มการเยาะเย้ยที่แพตช์ให้กับพารามิเตอร์ฟังก์ชันทดสอบของคุณเช่นใน def test_register_user(self, mock_target_scores):   -  person progmatico    schedule 19.04.2019
comment
สำหรับสิ่งที่ฉันทดสอบข้อความของคุณทั้งสองนั้นผิด   -  person warvariuc    schedule 19.04.2019
comment
ผิดเป็นคำอธิบายเพียงเล็กน้อย คุณทดสอบรหัสอะไร ตรวจสอบคำตอบของฉันก่อน หวังว่าจะช่วยได้   -  person progmatico    schedule 19.04.2019
comment
ที่จริงแล้วมันผิดเพียงเพราะคุณต้องแพตช์การตั้งค่าทั้งหมด ไม่ใช่แอตทริบิวต์ หรือดูที่นี่สำหรับ อีกทางเลือกหนึ่งหากคุณไม่ต้องการจำลองโมดูลการตั้งค่าทั้งหมด แต่เป็นเพียงแอตทริบิวต์ (ใช้ PropertyMock)   -  person progmatico    schedule 19.04.2019
comment
ฉันสังเกตว่าคุณไม่มีส่วน as ในคำสั่ง with ซึ่งหมายความว่าคุณไม่ต้องการเข้าถึงการเยาะเย้ยนอกเหนือจากการสร้างแพตช์ด้วย ซึ่งก็ใช้ได้เช่นกันสำหรับกรณีจำลองธรรมดาๆ หรือหากคุณตั้งค่าอ็อบเจ็กต์อื่นให้ส่งผ่านไปยังแพตช์ด้วย new   -  person progmatico    schedule 19.04.2019
comment
ฉันกำลังแก้ไขคำตอบของฉัน   -  person progmatico    schedule 19.04.2019
comment
แม้ว่าคำตอบของฉันจะใช้ได้ทั้งสองรูปแบบ แต่ฉันไม่สามารถสร้างข้อความแสดงข้อผิดพลาดที่แน่นอนโดยการเปลี่ยนพารามิเตอร์แพตช์และ def ในทางที่ผิดได้ เป็นไปได้ไหมที่คุณลืมใส่ self ใน class method ไปครู่หนึ่ง?   -  person progmatico    schedule 19.04.2019


คำตอบ (1)


ถ้าฉันเข้าใจสิ่งที่คุณกำลังพยายามทำ สิ่งนี้จะทำให้คุณมีแนวคิดว่าต้องทำอย่างไร

ฉันได้ให้ settings.py ระงับการมอบหมายเพียง False ถึง TARGET_SCORES_PER_SECTION การพูดถึง __main__ ในแพตช์นั้นน่ารำคาญเล็กน้อย มันจะไม่ยอมรับชื่อที่ไม่ผ่านการรับรอง

import unittest
from unittest import TestCase
from unittest.mock import patch
import settings


def register_user():
    return settings.TARGET_SCORES_PER_SECTION


class Test(TestCase):

    @patch('__main__.settings')
    def test_register_user(self, mock_settings):
        # setup your mock
        mock_settings.TARGET_SCORES_PER_SECTION = True
        # test your function
        self.assertTrue(register_user())

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

แก้ไข:

เนื่องจากฉันคิดว่าจะเข้าใจคำถาม OP ได้ดีขึ้น โค้ดด้านบนสามารถเปลี่ยนเป็นสิ่งนี้ได้หากคุณต้องการ:

import unittest
from unittest import TestCase
from unittest.mock import patch
import settings


def register_user():
    return settings.TARGET_SCORES_PER_SECTION


class Test(TestCase):

    @patch('settings.TARGET_SCORES_PER_SECTION', True)
    def test_register_user(self):
        self.assertTrue(register_user())

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

โดยที่ True คือพารามิเตอร์ new ออบเจ็กต์นี้ใช้เพื่อแก้ไขตำแหน่งที่คุณพูดถึงในสตริงการแก้ไข สิ่งนี้อาจจะดูหรูหรากว่า แต่คุณต้องมีวัตถุที่กำหนดค่าไว้สำหรับการเยาะเย้ย

person progmatico    schedule 19.04.2019
comment
โซลูชันของคุณใช้งานได้ แต่เป็นวิธีแก้ปัญหา คำถามของฉันเกี่ยวกับการใช้ mock.patch เป็นตัวตกแต่งตาม เอกสาร โดยส่งผ่านอาร์กิวเมนต์ new การส่งผ่านการเยาะเย้ยเป็นอาร์กิวเมนต์ของฟังก์ชันและการตั้งค่าในฟังก์ชันนั้นดูไม่ดีสำหรับฉัน ดูการอัปเดตคำถามของฉัน - person warvariuc; 19.04.2019
comment
@warvariuc แต่ฉันไม่ได้ทำ (ไม่ใช่ทางเลือก) นั่นเป็นคุณสมบัติมัณฑนากร มัณฑนากรเปลี่ยนลายเซ็นฟังก์ชันการทดสอบของคุณเพื่อเพิ่มการเยาะเย้ยเป็นพารามิเตอร์ คุณยังสามารถซ้อนมัณฑนากรได้ และพวกเขาจะเพิ่มการเยาะเย้ยทั้งหมดให้กับลายเซ็น แม้ว่าคุณจะไม่ได้ใช้มันข้างใน แต่ก็ต้องเขียนเป็น def นั่นเป็นเหตุผลที่คุณได้รับข้อผิดพลาดเกี่ยวกับ self - person progmatico; 19.04.2019
comment
คุณยังสามารถตกแต่งชั้นเรียนได้ นั่นจะเปลี่ยนลายเซ็นวิธีทดสอบทั้งหมด - person progmatico; 19.04.2019
comment
จริงๆแล้วมันเป็นทางเลือกขอโทษด้วย จากเอกสาร หากใช้ patch() เป็นตัวตกแต่งและละเว้น new การเยาะเย้ยที่สร้างขึ้นจะถูกส่งผ่านเป็นอาร์กิวเมนต์เพิ่มเติมสำหรับฟังก์ชันการตกแต่ง หากใช้ patch() เป็นตัวจัดการบริบท การจำลองที่สร้างขึ้นจะถูกส่งกลับโดยตัวจัดการบริบท - person progmatico; 19.04.2019
comment
ฉันพบปัญหา มันเป็นนักวิ่งทดสอบ Nose2 เมื่อฉันต้องการทดสอบวิธี TestCase เดียว (./manage.sh runtests -r -v tests.test_user.Test.test_register_user) มันจะผ่านฟังก์ชันที่ไม่ผูกกับ self ยังไม่ทราบว่าเหตุใดจึงเป็นเช่นนั้นและจะแก้ไขปัญหานี้อย่างไร แต่เป็นปัญหาที่แตกต่างออกไปแล้ว mock.patch ทำงานอย่างถูกต้อง ขอขอบคุณสำหรับเวลาของคุณ. - person warvariuc; 19.04.2019