简体   繁体   English

获取传递给 mock_open 的参数并为模拟调用不同的函数

[英]Get the argument passed to mock_open and call a different function for mock

I'd like to use mock_open to mock the functionality of opening a file, however, I'd like to know the actual argument passed:我想使用mock_open来模拟打开文件的功能,但是,我想知道传递的实际参数:

# module.py

file_path = "path/to/file"
with open(file_path, "r") as f:
    contents = f.read()
# test_module.py

from moto import mock_open
from unittest.mock import patch

def test_open():
    with patch("module.open", mock_open(
        with open(file_path) as f:
            contents = f.read()
        return contents
    ):

Now I know what you must be thinking, this is completely useless and stupid as it ruins the purpose of mock_open .现在我知道你一定在想什么,这是完全没用和愚蠢的,因为它破坏了mock_open的目的。

However, I actually want to mock a different function, namely, smart_open and instead of opening the file on S3, I have it in my local testing environment.但是,我实际上想模拟一个不同的函数,即smart_open ,而不是在 S3 上打开文件,而是在我的本地测试环境中使用它。 Hence, I'd like to use the file_path passed to smart_open , and then use open to get the actual contents.因此,我想使用传递给smart_openfile_path ,然后使用open来获取实际内容。 I also cannot use open directly, since the file_path passed to smart_open has a prefix of s3:// and I'd like to get rid of it.我也不能直接使用 open ,因为传递给smart_openfile_path有一个前缀s3:// ,我想摆脱它。

In essence, this is how it actually looks:本质上,这就是它的实际外观:

# module.py

from smart_open import open as smart_open

file_path = "s3://path/to/file"
with smart_open(file_path, "r") as f:
    contents = f.read()
# test_module.py

from moto import mock_open
from unittest.mock import patch
from utils import preprocess_path

def test_open():
    with patch("module.smart_open", mock_open(
        # something to pass to mock_open that says to do the following

        # get rid of the s3:// in the beginning
        file_path = preprocess_path(file_path)

        # get the contents using open instead of smart_open
        with open(file_path) as f:
            contents = f.read()

        return contents
    ):

Is it possible to do some preprocessing and call a different function (in this case open ) using the argument passed to smart_open ?是否可以使用传递给smart_open的参数进行一些预处理并调用不同的函数(在本例中为open )?

Do something like:做类似的事情:

@mock.patch("blah.blah.boto3.Session")
def test_open(m_session):
    m_open = mock.mock_open()
    with patch("module.smart_open", m_open, create=True):
        do_writing_function()
        m_open.return_value.write.assert_called_once_with(expected_stuff)

Basically you patch out smart_open's open with the mock_open, then you can read what mock_open's write is called with.基本上你用mock_open 修补smart_open 的open ,然后你可以读取mock_open 的写入被调用的内容。 call_args_list should also work here. call_args_list也应该在这里工作。

I patched boto3.Session myself to avoid dealing with the session stuff in my module, but since open is mocked, you won't actually try to open anything from the given filepath in the test.我自己修补了 boto3.Session 以避免处理我的模块中的会话内容,但是由于open是模拟的,因此您实际上不会尝试从测试中的给定文件路径中打开任何内容。

In my case, I also had my open()/writing in a separate function, which you might want to do as well.就我而言,我的 open()/writing 也在一个单独的函数中,您可能也想这样做。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM