非常基本的设置:
import mock
from mock import patch
def test_foo():
with patch.object(MyObject...):
# do some stuff here...
Run Code Online (Sandbox Code Playgroud)
PyCharm警告: Cannot find reference 'object' in 'function'.
如果要弹出mock.py,patch.object则定义为:
patch.object = _patch_object
Run Code Online (Sandbox Code Playgroud)
那么如何让警告消失呢?
我刚刚发现一堆单元测试失败了,因为开发人员没有在测试中嘲笑对redis客户端的依赖.我试图在这个问题上伸出援助之手,但我自己也有困难.
该方法写入redis客户端:
redis_client = get_redis_client()
redis_client.set('temp-facility-data', cPickle.dumps(df))
Run Code Online (Sandbox Code Playgroud)
稍后在断言中检索结果:
res = cPickle.loads(get_redis_client().get('temp-facility-data'))
expected = pd.Series([set([1, 2, 3, 4, 5])], index=[1])
assert_series_equal(res.variation_pks, expected)
Run Code Online (Sandbox Code Playgroud)
我设法成功修补了redis客户端的get()和set().
@mock.patch('redis.StrictRedis.get')
@mock.patch('redis.StrictRedis.set')
def test_identical(self, mock_redis_set, mock_redis_get):
mock_redis_get.return_value = ???
f2 = deepcopy(self.f)
f3 = deepcopy(self.f)
f2.pk = 2
f3.pk = 3
self.one_row(f2, f3)
Run Code Online (Sandbox Code Playgroud)
但我不知道如何设置return_value的get(),以什么样的set()将在代码中设置,从而使测试将通过.
现在,这条线未通过测试:
res = cPickle.loads(get_redis_client().get('temp-facility-data'))
TypeError: must be string, not MagicMock
Run Code Online (Sandbox Code Playgroud)
有什么建议吗?
我是Python的新手,所以如果这是一个重复或过于简单的问题我会道歉.我编写了一个协调器类,调用另外两个使用kafka-python库来发送/读取Kafka数据的类.我想为我的协调员课程编写一个单元测试,但是我很难弄清楚如何最好地解决这个问题.我希望我可以创建一个替代构造函数,我可以将我的模拟对象传递给,但这似乎不起作用,因为我得到一个错误,test_mycoordinator无法解决.我是否会以错误的方式测试这门课程?我应该测试一种pythonic方式吗?
这是我的测试类到目前为止的样子:
import unittest
from mock import Mock
from mypackage import mycoordinator
class MyTest(unittest.TestCase):
def setUpModule(self):
# Create a mock producer
producer_attributes = ['__init__', 'run', 'stop']
mock_producer = Mock(name='Producer', spec=producer_attributes)
# Create a mock consumer
consumer_attributes = ['__init__', 'run', 'stop']
data_out = [{u'dataObjectID': u'test1'},
{u'dataObjectID': u'test2'},
{u'dataObjectID': u'test3'}]
mock_consumer = Mock(
name='Consumer', spec=consumer_attributes, return_value=data_out)
self.coor = mycoordinator.test_mycoordinator(mock_producer, mock_consumer)
def test_send_data(self):
# Create some data and send it to the producer
count = 0
while count < 3:
count += 1 …Run Code Online (Sandbox Code Playgroud) 我有一个模块test.py,它使用键盘导入*从另一个模块keyboard.py导入函数.
在keyboard.py里面有两个功能:
def get_keys(keyList, timeStamped):
return event.getKeys(keyList=keyList, timeStamped=timeStamped)
def wait_keys(keyList, timeStamped):
return event.waitKeys(keyList=keyList, timeStamped=timeStamped)
Run Code Online (Sandbox Code Playgroud)
现在,我在test.py中的测试函数如下所示:
@mock.patch('keyboard.wait_keys')
@mock.patch('keyboard.get_keys')
def test_2(self, mock_waitKeys, mock_getKeys):
mock_waitKeys.return_value = [['wait_keys!', 0.1]]
mock_getKeys.return_value = [['get_keys!',0.1]]
run_blocks(trials,noise,win,expInfo, incorrect, tone1, tone2, experiment_details,allPoints,32,60)
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,我正在尝试将两个模拟返回值放在适当的位置.
然而,他们的影响似乎是倒置的!
当我在交互式控制台中调用它们而在断点处停止时(或在正常调用时检查值),两个模拟函数返回彼此的假返回值!
从控制台:
get_keys()
Out[2]: [['wait_keys!', 0.1]]
wait_keys()
Out[3]: [['get_keys!', 0.1]]
Run Code Online (Sandbox Code Playgroud)
我是否误解了传递给测试函数的模拟参数的顺序?
这可能与修补keyboard.get_keys而不是test.get_keys有关吗?
谢谢!路易丝
我有一个入口点函数main在一个对象上调用它,我想保持未被模拟,因为它在对象上调用了几个其他方法:
class Thing(object):
def main(self):
self.alpha()
self.bravo()
def alpha(self):
self.charlie()
def bravo(self):
raise TypeError("Requires Internet connection!")
def charlie(self):
raise Exception("Bad stuff happens here!")
Run Code Online (Sandbox Code Playgroud)
这很简单,可以手动模拟:
thing = Thing()
thing.alpha = MagicMock()
thing.bravo = MagicMock()
Run Code Online (Sandbox Code Playgroud)
我可以测试以确保alpha和bravo都被调用一次,我可以在alpha和bravo中设置副作用以确保它们被处理等等.
我担心的是,如果代码定义发生变化并且有人添加了一个charlie调用main.它没有被嘲笑,所以现在会感觉到副作用(而且它们就像写入文件,连接到数据库,从Internet上获取东西,因此这个简单的异常不会提醒我现在的测试坏).
我的计划是验证我的模拟对象不会调用其他方法而不是我应该说的方法(或者引发测试异常).但是,如果我做这样的事情:
MockThing = create_autospec(Thing)
thing = Thing()
thing.main()
print thing.method_calls
# [calls.main()]
Run Code Online (Sandbox Code Playgroud)
然后main也被嘲笑,所以它没有其他方法.我怎么能模仿每个方法但主要的方法呢?(我想要method_calls [calls.alpha(), calls.bravo()]).
编辑:用于黑客答案
好吧,我有一个非常hacky解决方案,但我希望有一个比这更好的答案.基本上我从原始类重新绑定方法(Python绑定一个未绑定的方法)
MockThing = create_autospec(Thing)
thing = MockThing()
thing.main = Thing.ingest.__get__(thing, Thing)
thing.main()
print thing.method_calls
# [calls.alpha(), …Run Code Online (Sandbox Code Playgroud) 哪种方式适合模拟和测试使用模拟库从open()返回的对象的代码?
whitelist_data.py:
WHITELIST_FILE = "testdata.txt"
format_str = lambda s: s.rstrip().lstrip('www.')
whitelist = None
with open(WHITELIST_FILE) as whitelist_data:
whitelist = set(format_str(line) for line in whitelist_data)
if not whitelist:
raise RuntimeError("Can't read data from %s file" % WHITELIST_FILE)
def is_whitelisted(substr):
return 1 if format_str(substr) in whitelist else 0
Run Code Online (Sandbox Code Playgroud)
这是我尝试测试它的方式.
import unittest
import mock
TEST_DATA = """
domain1.com
domain2.com
domain3.com
"""
class TestCheckerFunctions(unittest.TestCase):
def test_is_whitelisted_method(self):
open_mock = mock.MagicMock()
with mock.patch('__builtin__.open',open_mock):
manager = open_mock.return_value.__enter__.return_value
manager.__iter__ = lambda …Run Code Online (Sandbox Code Playgroud) 我试图在Djangos model.Manager()类上模拟一个链式调用.现在我想嘲笑values()和filter()方法.
为了测试我创建了一个小测试项目:
pip install django mock mock-django nose django-nosedjango-admin.py startproject mocktestmanage.py startapp mockmedjango_nose和mocktest.mockme以INSTALLED_APPS(settings.py)TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'到settings.py为了确保所有设置都正确,我跑了manage.py test.运行一个测试,Django在您创建应用程序时创建的标准测试.
我做的下一件事是创建一个非常简单的模型.
mockme/models.py
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=50)
Run Code Online (Sandbox Code Playgroud)
我做的下一件事是创建一个使用的简单函数MyModel.这是我想要稍后测试的功能.
mockme/functions.py
from models import MyModel
def chained_query():
return MyModel.objects.values('name').filter(name='Frank')
Run Code Online (Sandbox Code Playgroud)
这里没有什么特别的事情发生.该函数正在过滤MyModel对象以查找其中的所有实例name='Frank'.对values()的调用将返回一个ValuesQuerySet只包含所有找到的MyModel实例的name字段的内容.
mockme/tests.py
import mock
from django.test import TestCase
from mocktest.mockme.models import MyModel …Run Code Online (Sandbox Code Playgroud) 我有一个扩展unittest.TestCase的基类,我想修补那个基类,这样扩展这个基类的类也会应用补丁.
代码示例:
@patch("some.core.function", mocked_method)
class BaseTest(unittest.TestCase):
#methods
pass
class TestFunctions(BaseTest):
#methods
pass
Run Code Online (Sandbox Code Playgroud)
修补TestFunctions该类直接工作,但修补BaseTest类不会改变some.core.functionin 的功能TestFunctions.
我想声明Python类中的一个类方法调用另一个带有一组参数的classmethod.我希望模拟的classmethod是"spec-ed",因此它会检测是否使用错误的参数调用它.
当我使用patch.object(.., autospec=True, ..)classmethod 补丁时,classmethod被替换为a NonCallableMagicMock并在我尝试调用它时引发错误.
from mock import patch
class A(object):
@classmethod
def api_meth(cls):
return cls._internal_classmethod(1, 2, 3)
@classmethod
def _internal_classmethod(cls, n, m, o):
return sum(n, m, o)
with patch.object(A, '_internal_classmethod') as p:
print(type(p).__name__)
with patch.object(A, '_internal_classmethod', autospec=True) as p:
print(type(p).__name__)
Run Code Online (Sandbox Code Playgroud)
产生输出:
MagicMock
NonCallableMagicMock
Run Code Online (Sandbox Code Playgroud)
我怎样才能得到一个特定的模拟器来判断_internal_classmethod它所属的类何时不被嘲笑?
我不知道为什么我只是没有得到这个,但我想在Python中使用mock来测试我的函数是否在ftplib.FTP中正确调用函数.我把所有东西简化了下来,但仍然没有把它包裹起来.这是一个简单的例子:
import unittest
import ftplib
from unittest.mock import patch
def download_file(hostname, file_path, file_name):
ftp = ftplib.FTP(hostname)
ftp.login()
ftp.cwd(file_path)
class TestDownloader(unittest.TestCase):
@patch('ftplib.FTP')
def test_download_file(self, mock_ftp):
download_file('ftp.server.local', 'pub/files', 'wanted_file.txt')
mock_ftp.cwd.assert_called_with('pub/files')
Run Code Online (Sandbox Code Playgroud)
当我运行这个时,我得到:
AssertionError: Expected call: cwd('pub/files')
Not called
Run Code Online (Sandbox Code Playgroud)
我知道它必须使用模拟对象,因为这是一个虚假的服务器名称,并且在没有修补的情况下运行时,它会抛出"socket.gaierror"异常.
如何获取功能正在运行的实际对象?长期目标是在同一文件中没有"download_file"函数,而是从单独的模块文件中调用它.
python ×10
python-mock ×10
mocking ×5
unit-testing ×3
class-method ×1
django ×1
django-nose ×1
django-orm ×1
pycharm ×1
python-2.7 ×1
tdd ×1