簡體   English   中英

模擬整個 python 類

[英]Mock entire python class

我正在嘗試在 python 中進行一個簡單的測試,但我無法弄清楚如何完成模擬過程。

這是類和定義代碼:

class FileRemoveOp(...)
    @apply_defaults
    def __init__(
            self,
            source_conn_keys,
            source_conn_id='conn_default',
            *args, **kwargs):
        super(v4FileRemoveOperator, self).__init__(*args, **kwargs)
        self.source_conn_keys = source_conn_keys
        self.source_conn_id = source_conn_id


    def execute (self, context)
          source_conn = Connection(conn_id)
          try:
              for source_conn_key in self.source_keys:
                  if not source_conn.check_for_key(source_conn_key):    
                      logging.info("The source key does not exist")  
                  source_conn.remove_file(source_conn_key,'')
          finally:
              logging.info("Remove operation successful.")

這是我對執行函數的測試:

@mock.patch('main.Connection')
def test_remove_execute(self,MockConn):
    mock_coon = MockConn.return_value
    mock_coon.value = #I'm not sure what to put here#
    remove_operator = FileRemoveOp(...)
    remove_operator.execute(self)

由於execute方法嘗試建立連接,我需要模擬它,我不想建立真正的連接,只需返回一些模擬即可。 我怎樣才能做到這一點? 我習慣用 Java 做測試,但我從來沒有用過 python ..

首先,理解你總是需要模擬你試圖模擬的東西是非常重要的,如unittest.mock文檔中所述。

基本原則是在查找對象的位置打補丁,該位置不一定與定義的位置相同。

接下來您需要做的是返回一個MagicMock實例作為修補對象的return_value 因此,為了總結這一點,您需要使用以下序列。

  • 補丁對象
  • 准備要使用的MagicMock
  • 返回我們剛剛創建的MagicMock作為return_value

這是一個項目的快速示例。

connection.py(我們想要模擬的類)

class Connection(object):                                                        
    def execute(self):                                                           
        return "Connection to server made"

file.py(使用類的地方)

from project.connection import Connection                                        


class FileRemoveOp(object):                                                      
    def __init__(self, foo):                                                     
        self.foo = foo                                                           

    def execute(self):                                                           
        conn = Connection()                                                      
        result = conn.execute()                                                  
        return result    

測試/test_file.py

import unittest                                                                  
from unittest.mock import patch, MagicMock                                       
from project.file import FileRemoveOp                                            

class TestFileRemoveOp(unittest.TestCase):                                       
    def setUp(self):                                                             
        self.fileremoveop = FileRemoveOp('foobar')                               

    @patch('project.file.Connection')                                            
    def test_execute(self, connection_mock):
        # Create a new MagickMock instance which will be the
        # `return_value` of our patched object                                     
        connection_instance = MagicMock()                                        
        connection_instance.execute.return_value = "testing"

        # Return the above created `connection_instance`                     
        connection_mock.return_value = connection_instance                       

        result = self.fileremoveop.execute()                                     
        expected = "testing"                                                     
        self.assertEqual(result, expected)                                       

    def test_not_mocked(self):
        # No mocking involved will execute the `Connection.execute` method                                                   
        result = self.fileremoveop.execute()                                     
        expected = "Connection to server made"                                   
        self.assertEqual(result, expected) 

我發現這個簡單的解決方案在 python3 中有效:您可以在第一次導入之前替換整個類。 假設我必須從 real.manager 模擬“Manager”類

class MockManager:
    ...

import real.manager
real.manager.Manager = MockManager

如果沒有更好的地方,可以在init .py 中進行此替換。 它也可以在 python2 中工作,但我沒有檢查。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM