我需要一些模拟方面的帮助。
我在 mymodule.py 中有以下代码:
from someModule import external_function
class Class1(SomeBaseClass):
def method1(self, arg1, arg2):
external_function(param)
Run Code Online (Sandbox Code Playgroud)
现在我有测试代码:
import mock
from django.test import TestCase
from mymodule import class1
class Class1Test(TestCase)
def test_method1:
'''how can I mock external_function here?'''
Run Code Online (Sandbox Code Playgroud) 我将 Django 与 DRF 和 python 模拟一起使用。我想做的是测试我的视图并模拟序列化器和一些方法。
这就是我所拥有的:
views.py
from gmm_mobile.v1.serializers import RegisterParticipationSerializer
from gmm_mobile.v1.exceptions import GameOrCampaignDoesNotExist
from gmm_util.header import Header
from gmm_util.response import ResponseUtils
from gmm_util.permissions import MobileTokenPermission
from gmm_util.permissions import MobileTokenAuthentication
class ParticipantViewMobile(APIView):
permission_classes = (MobileTokenPermission, )
authentication_classes = (MobileTokenAuthentication, )
def post(self, request, service_id, campaign_id):
try:
environment_info = Header.get_environment_info(request)
request.data[Field.GAME_SERVICE_ID] = service_id
request.data[Field.CAMPAIGN] = campaign_id
request.data[Field.LOCATION] = environment_info
participation_serializer = RegisterParticipationSerializer(data=request.data)
participation_serializer.is_valid(raise_exception=True)
participation_serializer.save()
return ResponseUtils.created()
except Http404:
raise GameOrCampaignDoesNotExist()
Run Code Online (Sandbox Code Playgroud)
serializers.py
from gmm_mobile.v1.serializers import RegisterParticipationSerializer
from gmm_mobile.v1.exceptions import …Run Code Online (Sandbox Code Playgroud) python django django-unittest python-mock django-rest-framework
我正在尝试使用(反向移植)模块将间谍附加到类中的方法mock。也就是说,我想创建一个模拟,其工作原理与原始方法类似,但提供常用Mock功能call_count,例如等。
这是我当前使用的代码:
import mock
class MyClass(object):
def my_method(self, arg):
return arg + 1
def unit_under_test():
inst = MyClass()
return inst.my_method(1)
with mock.patch.object(MyClass, 'my_method', autospec=True,
side_effect=MyClass.my_method) as spy:
result = unit_under_test()
assert result == 2
assert spy.call_count == 1
Run Code Online (Sandbox Code Playgroud)
效果很好。现在我想使用 的自定义子类MagicMock来代替。文档说这可以通过参数patch来new_callable完成。但是,new_callable和autospec不能一起使用:
class MyMock(mock.MagicMock):
pass
with mock.patch.object(MyClass, 'my_method', autospec=True,
side_effect=MyClass.my_method,
new_callable=MyMock) as spy:
...
Run Code Online (Sandbox Code Playgroud)
Traceback (most recent call last):
File "./mocktest.py", line 19, in <module>
new_callable=MyMock) …Run Code Online (Sandbox Code Playgroud) 我有一个测试如下:
import mock
# other test code, test suite class declaration here
@mock.patch("other_file.another_method")
@mock.patch("other_file.open", new=mock.mock_open(read=["First line", "Second line"])
def test_file_open_and_read(self, mock_open_method, mock_another_method):
self.assertTrue(True) # Various assertions.
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
类型错误:test_file_open_and_read() 需要 3 个参数(给出 2 个)
我试图指定我想要__builtin__.open模拟另一个文件的方法,mock.mock_open而不是装饰器mock.MagicMock的默认行为patch。我怎样才能做到这一点?
当调用unittest.TestCase.assertEqual()两个复杂的字典时,我得到了一个很好的差异。
有什么办法可以从 Python 2.7 中获得差异mock.Mock.assert_called_with吗?我正在测试使用一些具有复杂值的 dict 参数的调用,当其中一个只是缺少一个布尔值时,很难看出问题是什么。
例如
AssertionError: Expected call: post('http://cloud-atlas.cogolo.net/api/executions', auth=('cloudatlas', 'cloudatlas'), data={'environment': 'hadoop', 'source': 'repo', 'output_path': 'hdfs://namenode-01/user/erose/testing', 'production': True, 'input_path': 'hdfs://namenode-01/foo/bar', 'name': 'linecount', 'mrcloud_options': '{"mrcloud_option_A": "foobar", "hadoop_user_name": "erose"}', 'details': '{"path_to_file": "linecount.py", "parameters": {}, "branch": "master", "repo_name": "example_repo"}'}, headers={'X-COGO-CLOUDATLAS-USER': 'erose'})
Actual call: post('http://cloud-atlas.cogolo.net/api/executions', auth=('cloudatlas', 'cloudatlas'), data={'input_path': 'hdfs://namenode-01/foo/bar', 'name': 'linecount', 'environment': 'hadoop', 'source': 'repo', 'output_path': 'hdfs://namenode-01/user/erose/testing', 'details': '{"path_to_file": "linecount.py", "parameters": {}, "branch": "master", "repo_name": "example_repo"}', 'mrcloud_options': '{"mrcloud_option_A": "foobar", "hadoop_user_name": "erose"}'}, headers={'X-COGO-CLOUDATLAS-USER': 'erose'})
Run Code Online (Sandbox Code Playgroud) 我有 python 文件
\n\n$ tree .\n.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 app\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 my_module.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 setup.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 test_my_module.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 tox.ini\n\n1 directory, 5 files\nRun Code Online (Sandbox Code Playgroud)\n\nmy_module.py
\n\n$ cat app/my_module.py\nfrom pymongo import MongoClient\n\nclient = MongoClient(\'mongodb://localhost:27017/\')\n\npost = client.test_database.posts.find_one()\n\ndef ret_value():\n return db.posts\nRun Code Online (Sandbox Code Playgroud)\n\n毒物文件
\n\n$ cat tox.ini\n[tox]\nenvlist = py35\n\n[testenv]\ndeps=\n coverage>=4.1\n flake8\n pylint\n pytest-cov==2.2.1\n pytest==3.0.7\n pytest-mock\n pytest-xdist\n pymongo\n mock\ncommands=py.test -n 5 -l\nsetenv =\n XYZ = 123\nRun Code Online (Sandbox Code Playgroud)\n\n测试我的模块.py
\n\n$ cat test_my_module.py\nimport os\n\nimport mock\n\nwith mock.patch(\'app.my_module.MongoClient\'):\n from app import my_module\n\ndef test_my_module_method():\n assert os.getenv(\'XYZ\') == \'123\'\nRun Code Online (Sandbox Code Playgroud)\n\n在 中my_module.py …
是否可以在继续使用同名其他字段/函数的生产版本的同时模拟 python 构造函数?例如,给定生产代码:
class MyClass:
class SubClass:
def __init__(self) -> None:
print("\nreal sub init called")
class SubSubClass:
def __init__(self) -> None:
print("\nreal sub sub init called")
Run Code Online (Sandbox Code Playgroud)
以及以下测试代码:
class FakeSubClass:
def __init__(self) -> None:
print("\nfake init called")
def test():
MyClass.SubClass()
MyClass.SubClass.SubSubClass()
MyClass.SubClass = Mock(side_effect=FakeSubClass)
MyClass.SubClass()
MyClass.SubClass.SubSubClass()
Run Code Online (Sandbox Code Playgroud)
我们得到以下输出:
real sub init called
real sub sub init called
fake init called
Run Code Online (Sandbox Code Playgroud)
请注意,最后一行MyClass.SubClass.SubSubClass()没有创建真正的 SubSubClass,因为此时它是 SubClass 模拟的自动创建的属性。
我想要的输出如下:
real sub init called
real sub sub init called
fake init called
real sub sub …Run Code Online (Sandbox Code Playgroud) 我想模拟init .py 中的一个方法,但实际上它不起作用。
有一个示例来演示该问题以及我如何尝试编写单元测试:
被测代码:src.main.myfile:
from src.main.utils import a_plus_b
def method_under_test():
a_plus_b()
Run Code Online (Sandbox Code Playgroud)
a_plus_b位于src.main.utils模块中的__init__.py中:
def a_plus_b():
print("a + b")
Run Code Online (Sandbox Code Playgroud)
单元测试:
import src.main.utils
import unittest
from mock import patch
from src.main.myfile import method_under_test
class my_Test(unittest.TestCase):
def a_plus_b_side_effect():
print("a_plus_b_side_effect")
@patch.object(utils, 'a_plus_b')
def test(self, mock_a_plus_b):
mock_a_plus_b.side_effect = self.a_plus_b_side_effect
method_under_test()
Run Code Online (Sandbox Code Playgroud)
单元测试打印“a + b”,而不是副作用。谁能帮我解决我做错了什么?
我目前拥有的是:
def some_method():
some_obj = some_other_method()
# This is what I want to mock return value of:
some_obj.some_obj_some_method()
@patch('some_package.some_other_method')
def test_some_stuff(some_other_method_patch):
some_other_method_patch.return_value = SomeObject()
Run Code Online (Sandbox Code Playgroud)
我怎样才能将 some_obj.some_obj_some_method() 返回值设置为 False?
考虑以下文件:
圣手手榴弹.py
def count(one, two, five='three'):
print('boom')
Run Code Online (Sandbox Code Playgroud)
test_holy_hand_grenade.py
from unittest import mock
import holy_hand_grenade
def test_hand_grenade():
mock_count = mock.patch("holy_hand_grenade.count", autospec=True)
with mock_count as fake_count:
fake_count(1, 2, five=5)
# According to https://docs.python.org/3/library/unittest.mock.html#unittest.mock.Mock.call_args
# this should work
assert fake_count.call_args.kwargs['five'] == 5
Run Code Online (Sandbox Code Playgroud)
根据文档,call_args应该是:
这要么是 None (如果尚未调用模拟),要么是最后一次调用模拟的参数。这将采用元组的形式:第一个成员,也可以通过 args 属性访问,是调用模拟的任何有序参数(或空元组),第二个成员,也可以通过访问kwargs 属性是任何关键字参数(或空字典)。
(强调我的)
但这在我的脸上炸开了锅 TypeError: tuple indices must be integers or slices, not str
嗯。不?
我真的不明白的是,如果这是一个调用对象,它就是,因为
assert isinstance(fake_count.call_args, (mock._Call,))
Run Code Online (Sandbox Code Playgroud)
通过,它应该有 kwargs 和 args。它……嗯,确实如此。但它们似乎实际上并不是正确的:
assert isinstance(fake_count.call_args.kwargs, (mock._Call,)) #this works
assert isinstance(fake_count.call_args.kwargs, (dict,)) # doesn't …Run Code Online (Sandbox Code Playgroud) python ×10
python-mock ×10
mocking ×6
unit-testing ×6
python-2.7 ×2
django ×1
pytest ×1
python-3.x ×1