首页 > 解决方案 > 尝试使用补丁来模拟 BlobServiceClient 但调用了真正的类

问题描述

我有以下课程

from azure.storage.blob import BlobServiceClient

class FooContainer:
    def __init__(self, project_id, account_url, sas_token):
        service_client = BlobServiceClient(account_url, credential=sas_token)
        self.container_client = service_client.get_container_client("foo")
        self.blob_name = f"{project_id}.foo.json"

    def upload(self, text):
        print(text)
        self.container_client.upload_blob(name=self.blob_name, data=text, overwrite=True)

我想测试当我调用正确调用时,所以我有以下upload测试container_client.upload_blob

from unittest import mock
from foo_container import FooContainer

@mock.patch('azure.storage.blob.BlobServiceClient', autospec=True)
def test_init(mockBlobServiceClient):
    container = FooContainer("x", "y", "z")

    container.upload("some text")

    mockBlobServiceClient.container_client.upload_blob.assert_called_with(
        name="x.foo.json", data="some text", overwrite=True)

当我运行测试时python3 -m pytest test_foo_container.py,看起来 BlobServiceClient 根本没有被嘲笑,因为测试失败了FAILED test_foo_container.py::test_init - ValueError: Unable to determine account name for shared key credential.

完整的失败日志是

================================================================================================= FAILURES =================================================================================================
________________________________________________________________________________________________ test_init _________________________________________________________________________________________________

mockBlobServiceClient = <MagicMock name='BlobServiceClient' spec='BlobServiceClient' id='4572408592'>

    @mock.patch('azure.storage.blob.BlobServiceClient', autospec=True)
    def test_init(mockBlobServiceClient):
>       container = FooContainer("x", "y", "z")

test_foo_container.py:6: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
foo_container.py:5: in __init__
    service_client = BlobServiceClient(account_url, credential=sas_token)
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/azure/storage/blob/_blob_service_client.py:126: in __init__
    super(BlobServiceClient, self).__init__(parsed_url, service='blob', credential=credential, **kwargs)
/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/azure/storage/blob/_shared/base_client.py:90: in __init__
    self.credential = format_shared_key_credential(account, credential)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

account = ['y'], credential = 'z'

    def format_shared_key_credential(account, credential):
        if isinstance(credential, six.string_types):
            if len(account) < 2:
>               raise ValueError("Unable to determine account name for shared key credential.")
E               ValueError: Unable to determine account name for shared key credential.

/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/azure/storage/blob/_shared/base_client.py:324: ValueError

我究竟做错了什么?为什么BlobServiceClient不嘲笑而使用真正的类呢?

标签: pythonpytestazure-blob-storage

解决方案


模拟时,我们必须指定要使用模拟的模块,而不仅仅是模拟的模块。

一个独立的例子:

src/hello.py

def do_something_under_test():
    open('my_file')

测试/test_hello.py

import mock

from src import hello


@mock.patch('src.hello.open')
def test_hello(mock_open):
    hello.do_something_under_test()
    mock_open.assert_called_with('my_file')

请注意,我们不模拟open,但是src.hello.open

在您的示例中,尝试@mock.patch('azure.storage.blob.BlobServiceClient')使用模块FooContainer在以下位置定义的开头:foo_container.

我怀疑答案是@mock.patch('foo_container.BlobServiceClient')——这是因为你是如何导入BlobServiceClient.


推荐阅读