python - Python - 调用 psutil.process_iter 的模拟方法中的错误
问题描述
我有一个方法(如下),在一个用于查找和生成进程信息的模块utils.py
中psutil.process_iter
。dicts ( psutil.Process.as_dict
) 基于给定进程的名称。如果进程名称不存在,或者遇到进程错误,则不会生成任何内容。该模块当然包含psutil
.
def get_processes_by_name(process_name):
for proc in psutil.process_iter():
try:
pinfo = proc.as_dict()
if process_name == pinfo['name']:
yield pinfo
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
我正在尝试为此方法编写许多单元测试,用于不同的场景,使用unittest.mock
. 测试用例位于测试模块test_utils.py
中。下面是一个例子。
def test__process_instances_by_name__one_running_proc_matches_given_proc_name__one_proc_instance_generated(self):
mock_proc1 = MagicMock()
mock_proc1.as_dict = MagicMock(return_value={'name': 'some_other_proc_name'})
mock_proc2 = MagicMock()
mock_proc2.as_dict = MagicMock(side_effect=psutil.AccessDenied(2))
mock_proc3 = MagicMock()
mock_proc3.as_dict = MagicMock(return_value={'name': 'test_proc_name', 'exe': 'test/proc/exec/path', 'pid': 3})
with patch('utils.psutil.process_iter', MagicMock()) as mock_process_iter:
mock_process_iter.iter.return_value = iter([mock_proc1, mock_proc2, mock_proc3])
received_process_instances = list(get_processes_by_name('test_proc_name'))
self.assertEqual(received_process_instances, [mock_proc3])
请注意,我不是psutil.process_iter
直接打补丁,而是将其导入到utils.py
定义目标方法的目标模块中。我认为是正确的做法。
在这个测试用例中,我创建了三个模拟进程mock_proc1
:第一个(具有所需名称的有效进程。这个想法是,使用方法调用时应该只生成。作为生成器(以下),我遵循了有关如何模拟生成方法的文档。psutil.AccessDenied
as_dict
mock_proc2
mock_proc3
test_proc_name
get_processes_by_name
test_proc_name
mock_proc3
get_processes_by_name
psutil.process_iter
unittest
不幸的是,这个测试用例失败了——目标方法没有生成任何东西,所以断言失败(ipdb
下面的输出)。
ipdb>
> /path/to/tests/test_utils.py(352)test__get_processes_by_name__one_running_proc_matches_given_proc_name__one_proc_instance_generated()
351
--> 352 self.assertEqual(received_process_instances, [mock_proc3])
353
ipdb>
AssertionError: Lists differ: [] != [<MagicMock id='4660019536'>]
Second list contains 1 additional elements.
First extra element 0:
<MagicMock id='4660019536'>
我尝试使用ipdb
(在目标方法的顶部放置断点)调试目标方法,我可以看到以下输出。
> /path/to/utils.py(183)get_processes_by_name()
182 import ipdb; ipdb.set_trace()
--> 183 for proc in psutil.process_iter():
184 try:
ipdb>
ipdb> n
StopIteration
> /path/to/venv/lib/python3.7/site-packages/pluggy/callers.py(203)_multicall()
202 try:
--> 203 gen.send(outcome)
204 _raise_wrapfail(gen, "has second yield")
ipdb>
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
[... skipped 1 hidden frame]
我不知道这里发生了什么。是在抱怨中的多个产量psutil.process_iter
,还是在嘲笑中存在错误。欢迎大家提出意见。
解决方案
推荐阅读
- python - Python 2.x 到 3.x - 附加语法错误:如何使其与 2.x 中的 Python 3.x 兼容?
- python - 使用 Python 抓取网页价格
- r - Rmarkdown:为每个子组添加一个标题和一个图
- javascript - Ajax 没有调用 php 文件
- swiftui - 使用 LazyVStack 在 Mac 应用程序中重新排序 SwiftUI 列表
- javascript - 在多个数组中组合“列”
- python - Python上的Selenium未连接到任何浏览器
- installation - 2SXC 安装中的许多错误和错误
- javascript - 我正在 Pitney Bowes 网站上跟踪包裹 我无法使用 excel VBA 启用搜索按钮
- python - 如何在不占用 Python 中所有 CPU 时间的情况下通过网络使用字节流