具有模拟响应的测试方法,不创建数据
Test method with a mock response, without create data
我正在使用 unittest 方法测试 createData,它会在我的数据库中创建一些内容。
def createData(self, content):
logging.info("Creating data...")
request = requests.post(self.url, data=content)
if request.status_code == 201:
logging.info("Data created")
else:
logging.error("Data not created")
return request
所以我创建了两个测试:一个是我创建数据失败的 self.assertNotEqual(201, badRequest.status_code)
,另一个是我成功的 self.assertEqual(201, goodRequest.status_code)
。当然,之后,我删除了这个数据。
我想在不创建任何数据的情况下进行此测试。所以我嘲笑这样的回应:
import unittest, logging
from data import Data as data
from unittest.mock import Mock
class TestData(unittest.TestCase):
def testCreateDataSuccess(self):
mock_response = Mock()
mock_response.status_code = 201
with self.assertLogs() as captured:
data.createData(data, goodContent).return_value = mock_response
self.assertEqual(201, mock_response.status_code)
self.assertEqual(captured.records[1].levelname, 'INFO')
然而,尽管模拟了,但在我的数据库中创建了一个数据。你能告诉我我不明白的地方吗?
感谢您的帮助!
模拟通常使用 mock.patch
应用。您要模拟的是 requests.post
的响应,而不是 createData
的响应。弄清楚在哪里模拟可能非常棘手。本指南可以帮助 (https://alexmarandon.com/articles/python_mock_gotchas/)
您可能需要修改导入被测代码的方式,以便能够在正确的位置进行模拟。
import unittest, logging
import data # We are importing the entire module. This will let us patch in the correct location
from unittest.mock import Mock
class TestData(unittest.TestCase):
def testCreateDataSuccess(self):
mock_response = Mock()
mock_response.status_code = 201
# using mock.patch, we can replace the response from requests.post with our mock value. `requests` is imported in the `data` module so we mock `data.requests`
with mock.patch(data.requests.post, return_value=mock_response):
with self.assertLogs() as captured:
data.Data.createData(data, goodContent)
# self.assertEqual(201, mock_response.status_code) This line does not actually do anything - it's just testing that our mock has the status code we set. But we already know that, because we set it just a few lines ago.
self.assertEqual(captured.records[1].levelname, 'INFO')
好吧,我找到了解决这个问题的方法:使用补丁装饰器。
我猜它“化解”了数据中的请求 post,用配置的模拟
代替响应
import unittest, logging
from data import Data as data
from unittest.mock import patch
class TestData(unittest.TestCase):
@patch('data.requests.post')
def testCreateDataSuccess(self, mock_post):
mock_post.return_value.status_code = 201
with self.assertLogs() as captured:
response = data.createData(data, goodContent)
self.assertEqual(201, response.status_code)
self.assertEqual(captured.records[1].levelname, 'INFO')
我正在使用 unittest 方法测试 createData,它会在我的数据库中创建一些内容。
def createData(self, content):
logging.info("Creating data...")
request = requests.post(self.url, data=content)
if request.status_code == 201:
logging.info("Data created")
else:
logging.error("Data not created")
return request
所以我创建了两个测试:一个是我创建数据失败的 self.assertNotEqual(201, badRequest.status_code)
,另一个是我成功的 self.assertEqual(201, goodRequest.status_code)
。当然,之后,我删除了这个数据。
我想在不创建任何数据的情况下进行此测试。所以我嘲笑这样的回应:
import unittest, logging
from data import Data as data
from unittest.mock import Mock
class TestData(unittest.TestCase):
def testCreateDataSuccess(self):
mock_response = Mock()
mock_response.status_code = 201
with self.assertLogs() as captured:
data.createData(data, goodContent).return_value = mock_response
self.assertEqual(201, mock_response.status_code)
self.assertEqual(captured.records[1].levelname, 'INFO')
然而,尽管模拟了,但在我的数据库中创建了一个数据。你能告诉我我不明白的地方吗?
感谢您的帮助!
模拟通常使用 mock.patch
应用。您要模拟的是 requests.post
的响应,而不是 createData
的响应。弄清楚在哪里模拟可能非常棘手。本指南可以帮助 (https://alexmarandon.com/articles/python_mock_gotchas/)
您可能需要修改导入被测代码的方式,以便能够在正确的位置进行模拟。
import unittest, logging
import data # We are importing the entire module. This will let us patch in the correct location
from unittest.mock import Mock
class TestData(unittest.TestCase):
def testCreateDataSuccess(self):
mock_response = Mock()
mock_response.status_code = 201
# using mock.patch, we can replace the response from requests.post with our mock value. `requests` is imported in the `data` module so we mock `data.requests`
with mock.patch(data.requests.post, return_value=mock_response):
with self.assertLogs() as captured:
data.Data.createData(data, goodContent)
# self.assertEqual(201, mock_response.status_code) This line does not actually do anything - it's just testing that our mock has the status code we set. But we already know that, because we set it just a few lines ago.
self.assertEqual(captured.records[1].levelname, 'INFO')
好吧,我找到了解决这个问题的方法:使用补丁装饰器。 我猜它“化解”了数据中的请求 post,用配置的模拟
代替响应import unittest, logging
from data import Data as data
from unittest.mock import patch
class TestData(unittest.TestCase):
@patch('data.requests.post')
def testCreateDataSuccess(self, mock_post):
mock_post.return_value.status_code = 201
with self.assertLogs() as captured:
response = data.createData(data, goodContent)
self.assertEqual(201, response.status_code)
self.assertEqual(captured.records[1].levelname, 'INFO')