簡體   English   中英

上下文管理器的模擬失敗,出現AttributeError:__ exit__

[英]Mock for context-manager fails with AttributeError: __exit__

我正在嘗試使用Mock修補一些上下文管理器功能,因此我可以測試代碼在給出好,壞和垃圾輸入的情況下做出明智的事情。 這是帶有with語句的測試代碼。 補丁在我的代碼中的正確位置完成。

@patch("__main__.opened_w_error")
def test_get_recipe_file(self, mo):
    mo.return_value = (Mock(), None)
    mo.__enter__ = Mock(return_value=None)
    mo.__exit__ = Mock(return_value=None)
    with mo(…) as (fd, err):  # AttributeError: __exit__ is raised here.
        print(fd)
        print(err)

但是, with mo(…) as (fd, err)會引發AttributeError: __exit__

模擬魔術方法文檔說明你應該使用它

with mo as (fd, err):
    …

后一段代碼是我試圖嘲笑的。 但這不是我在代碼中使用它的方式。 對於那些真正感興趣的人,我試圖在PEP 343中模擬示例6的opened_w_error()來處理打開文件和捕獲錯誤。 因此代碼是:

with open_w_error(filename, 'r') as (fd, err):
    …

后者是我想要嘲笑的。

請注意,您傳遞到with語句的對象是,應該有一個__enter____exit__方法,從返回值__enter__用於as結構。 在你的情況下,你正在調用mo(...) ,它返回(Mock(), None) ,這不是一個上下文管理器。 您應該將此返回值移動到__enter__方法。

@patch("__main__.opened_w_error")
def test_get_recipe_file(self, mo):
    mo.__enter__ = Mock(return_value=(Mock(), None))
    mo.__exit__ = Mock(return_value=None)
    with mo as (fd, err):
        print(fd)
        print(err)

編輯 :如果您仍想調用mo ,則將其返回值設為上下文管理器。

@patch("__main__.opened_w_error")
def test_get_recipe_file(self, m_opened_w_error):
    mo = Mock()
    mo.__enter__ = Mock(return_value=(Mock(), None))
    mo.__exit__ = Mock(return_value=None)
    m_opened_w_error.return_value = mo
    with m_opened_w_error(...) as (fd, err):
        print(fd)
        print(err)

問題是當你調用mo(..)它返回的對象( tuple )沒有__enter____exit__屬性。

為了解決這個問題分配momoreturn_value使上下文管理屬性你就可以設置仍然可以發現。

@patch("__main__.opened_w_error")
def test_get_recipe_file(self, mo):
    mo.return_value = mo
    mo.__enter__ = Mock(return_value=(Mock(), None))
    mo.__exit__ = Mock(return_value=None)
    with mo('file', 'r') as (fd, err): 
        print(fd)
        print(err)
        mo.assert_called_once_with('file', 'r')  # Should be True

你需要的是這個:

with mock.patch('__main__.opened_w_error') as mo:
    mo.__enter__ = Mock(return_value=(Mock(), None))
    mo.__exit__ = Mock(return_value=None)
    # Your code goes here

暫無
暫無

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

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