2017-05-12 101 views
0

我一直在尋找堆棧交換和網絡周圍如何做到這一點,但我不明白如何嘲笑方法的行爲。我正在嘗試爲我的自定義類模擬openpyxl行爲和行爲。這是我的嘗試:嘲諷方法在Python中調用

import unittest 
from unittest.mock import MagicMock 
import openpyxl 
from MyPythonFile import MyClass 

class TestMyClass(unittest.TestCase): 
    def test_myclass(self): 
    myclass = MyClass() 
    wb = openpyxl.workbook() 
    ws = openpyxl.worksheet() 
    wbPath = 'wbPath' 

    openpyxl.load_workbook(wbPath, data_only = True) = MagicMock(return_value=wb) 

當我嘗試最後一行時,我得到錯誤「無法分配給函數調用」。我需要使用patch.object('openpyxl','load_workbook')嗎?我習慣於用Groovy在Java中嘲笑,而且非常簡單。

*編輯:想那config.get給出與side_effect參數多的回報基礎上添加從@alxwrd

import unittest 
from unittest.mock import MagicMock 
import openpyxl 
import configparser 
from MyPythonFile import MyClass 

class TestMyClass(unittest.TestCase): 
    def test_myclass(self): 
    myclass = MyClass() 
    wb = openpyxl.workbook() 
    ws = openpyxl.worksheet() 
    config = configparser.ConfigParser() 

    openpyxl.load_workbook = MagicMock(return_value=wb) 
    wb.get_sheet_by_name = MagicMock(return_value=ws) 

    config.sections() = MagicMock(return_value=['Section1']) 
    config.get = MagicMock(side_effect=['Value1','Value2']) 

通知的響應測試的最終版本,所以如果config.get()被調用一次代碼返回'Value1',當config.get()被第二次調用時,返回'Value2'

回答

2

您不能覆蓋函數調用,但您可以覆蓋該函數本身。

docs

你的情況
>>> from unittest.mock import MagicMock 
>>> thing = ProductionClass() 
>>> thing.method = MagicMock(return_value=3) 
>>> thing.method(3, 4, 5, key='value') 
3 
>>> thing.method.assert_called_with(3, 4, 5, key='value') 

所以:

openpyxl.load_workbook = MagicMock(return_value=wb) 
+0

好,偉大,對於裝載工作簿的工作,但如果我想嘲笑同樣的方法,但使用不同的參數,並使其返回的值不同?例如,如果我模擬'config = configparser.ConfigParser()',然後我想模擬'config.get('Section1','Value1')= MagicMock(return_value ='val1')''和'config.get 'Section1','Value2')= MagicMock(return_value ='val2')'? – EliSquared

+0

您可以訪問使用'.call_args'傳遞的參數,並更新'.return_value'返回的內容。 https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.call_args https://docs.python.org/3/library/unittest.mock.html #unittest.mock.Mock.return_value – alxwrd

1

您不必導入你想在你的單元測試嘲笑的對象。使用patch來模擬目標。假設你的代碼有這個導入語句:import openpyxl。然後打補丁可以在您的測試可以用作decorator

import unittest 
from unittest import mock 
from MyPythonFile import MyClass 

class TestMyClass(unittest.TestCase): 

    @mock.patch('MyPythonFile.openpyxl') 
    def test_myclass(self, openpyxl_mock): 
     wb_dummy = 'foo' 
     openpyxl_mock.load_workbook.return_value = wb_dummy 

     myclass = MyClass() 
     myclass.load_workbook() # assuming this calls openpyxl.load_workbook() 

注意,您必須添加一個參數的測試方法,將獲得的模擬對象。

或者作爲context manager

import unittest 
from unittest import mock 
from MyPythonFile import MyClass 

class TestMyClass(unittest.TestCase): 

    def test_myclass(self): 
     with mock.patch('MyPythonFile.openpyxl') as openpyxl_mock: 
      wb_dummy = 'foo' 
      openpyxl_mock.load_workbook.return_value = wb_dummy 

      myclass = MyClass() 
      myclass.load_workbook() # assuming this calls openpyxl.load_workbook()