Python unittest.mock google 存储 - 如何实现 exceptions.NotFound 作为副作用
Python unittest.mock google storage - how to achieve exceptions.NotFound as side effect
我在 Python 中阅读了一些关于模拟的 tutorials,但我仍在努力:-/
例如,我有一个函数包装了对 google 存储的调用以写入 blob。
我想将 google.storage.Client().bucket(bucket_name) 方法模拟为 return 和 exceptions.NotFound 用于特定的不存在的存储桶。
我正在使用 side_effect 设置异常
你知道我做错了什么吗?
以下是我尝试过的(我使用了 2 个文件:main2.py 和 main2_test.py) :
# main2.py
import logging
from google.cloud import storage
def _write_content(bucket_name, blob_name, content):
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(blob_name)
try:
blob.upload_from_string(data=content)
return True
except Exception:
logging.error("Failed to upload blob")
raise
和
# main2_test.py
import pytest
from unittest.mock import patch
from google.api_core import exceptions
import main2
@patch("main2.storage.Client", autospec=True)
def test_write_content(clientMock):
bucket_name = "not_existent_bucket"
clientMock().bucket(bucket_name).side_effect = exceptions.NotFound
with pytest.raises(exceptions.NotFound):
main2._write_content(bucket_name, "a_blob_name", '{}')
调用示例[=19=]
pytest main2_test.py::test_write_content
结果
platform linux -- Python 3.7.7, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: /home/user/project, inifile: pytest.ini
plugins: requests-mock-1.8.0
collected 1 item
main2_test.py::test_write_content FAILED [100%]
============================================================================================== FAILURES ==============================================================================================
_________________________________________________________________________________________ test_write_content _________________________________________________________________________________________
clientMock = <MagicMock name='Client' spec='Client' id='139881522497360'>
@patch("main2.storage.Client", autospec=True)
def test_write_content(clientMock):
bucket_name = "my_bucket"
clientMock().bucket(bucket_name).side_effect = exceptions.NotFound
with pytest.raises(exceptions.NotFound):
> main2._write_content(bucket_name, "a_blob_name", '{}')
E Failed: DID NOT RAISE <class 'google.api_core.exceptions.NotFound'>
main2_test.py:14: Failed
=====================================
FAILED main2_test.py::test_write_content - Failed: DID NOT RAISE <class 'google.api_core.exceptions.NotFound'>
=====================================
您的测试有两个问题:您没有模拟实际引发的方法 (upload_from_string
),并且您正在设置异常 class而不是作为副作用的异常。
以下方法可行:
@patch("main2.storage.Client", autospec=True)
def test_write_content(clientMock):
blob_mock = clientMock().bucket.return_value.blob.return_value # split this up for readability
blob_mock.upload_from_string.side_effect = exceptions.NotFound('testing') # the exception is created here
with pytest.raises(exceptions.NotFound):
main2._write_content("not_existent", "a_blob_name", '{}')
另请注意,为 bucket
调用设置特定参数没有任何效果,因为它是在模拟上调用的,参数只是被忽略了——我用 return_value
替换了它使这一点更清楚。
我在 Python 中阅读了一些关于模拟的 tutorials,但我仍在努力:-/
例如,我有一个函数包装了对 google 存储的调用以写入 blob。
我想将 google.storage.Client().bucket(bucket_name) 方法模拟为 return 和 exceptions.NotFound 用于特定的不存在的存储桶。 我正在使用 side_effect 设置异常
你知道我做错了什么吗?
以下是我尝试过的(我使用了 2 个文件:main2.py 和 main2_test.py) :
# main2.py
import logging
from google.cloud import storage
def _write_content(bucket_name, blob_name, content):
storage_client = storage.Client()
bucket = storage_client.bucket(bucket_name)
blob = bucket.blob(blob_name)
try:
blob.upload_from_string(data=content)
return True
except Exception:
logging.error("Failed to upload blob")
raise
和
# main2_test.py
import pytest
from unittest.mock import patch
from google.api_core import exceptions
import main2
@patch("main2.storage.Client", autospec=True)
def test_write_content(clientMock):
bucket_name = "not_existent_bucket"
clientMock().bucket(bucket_name).side_effect = exceptions.NotFound
with pytest.raises(exceptions.NotFound):
main2._write_content(bucket_name, "a_blob_name", '{}')
调用示例[=19=]
pytest main2_test.py::test_write_content
结果
platform linux -- Python 3.7.7, pytest-5.4.3, py-1.9.0, pluggy-0.13.1
rootdir: /home/user/project, inifile: pytest.ini
plugins: requests-mock-1.8.0
collected 1 item
main2_test.py::test_write_content FAILED [100%]
============================================================================================== FAILURES ==============================================================================================
_________________________________________________________________________________________ test_write_content _________________________________________________________________________________________
clientMock = <MagicMock name='Client' spec='Client' id='139881522497360'>
@patch("main2.storage.Client", autospec=True)
def test_write_content(clientMock):
bucket_name = "my_bucket"
clientMock().bucket(bucket_name).side_effect = exceptions.NotFound
with pytest.raises(exceptions.NotFound):
> main2._write_content(bucket_name, "a_blob_name", '{}')
E Failed: DID NOT RAISE <class 'google.api_core.exceptions.NotFound'>
main2_test.py:14: Failed
=====================================
FAILED main2_test.py::test_write_content - Failed: DID NOT RAISE <class 'google.api_core.exceptions.NotFound'>
=====================================
您的测试有两个问题:您没有模拟实际引发的方法 (upload_from_string
),并且您正在设置异常 class而不是作为副作用的异常。
以下方法可行:
@patch("main2.storage.Client", autospec=True)
def test_write_content(clientMock):
blob_mock = clientMock().bucket.return_value.blob.return_value # split this up for readability
blob_mock.upload_from_string.side_effect = exceptions.NotFound('testing') # the exception is created here
with pytest.raises(exceptions.NotFound):
main2._write_content("not_existent", "a_blob_name", '{}')
另请注意,为 bucket
调用设置特定参数没有任何效果,因为它是在模拟上调用的,参数只是被忽略了——我用 return_value
替换了它使这一点更清楚。