python - 用于测试的模拟密码哈希

标签 python pytest

我试图通过模拟大多数测试的密码哈希来加快我的 Flask 应用程序的测试速度。我在 Windows 上使用 pytest 和 Python 3.8。

我尝试过以下方法:

import pytest
import werkzeug.security

@pytest.fixture(autouse=True)
def mock_password_hash(monkeypatch, request):
    if "no_mock_password_hash" in request.keywords:
        pass
    else:
        def mock_hash(*args, **kwargs):
            return "123456"

         monkeypatch.setattr(werkzeug.security, 'generate_password_hash', mock_hash)

import pytest
import werkzeug.security
from unittest import mock


@pytest.fixture(autouse=True)
def mock_password_hash(request):
    """
    Mocks the built in method hashlib.pbkdf2 to decrease test runtime.
    """
    if "no_mock_password_hash" in request.keywords:
        yield None
    else:
        with mock.patch.object(
            werkzeug.security, 'generate_password_hash', return_value="123456"
        ) as _mocked_hash:
            yield _mocked_hash

我已经使用此测试测试了上述两种装置:

def test_hash_autouse():
    g = Guest(0, 'username', 'password', 'name', 'email')
    assert g.password == '123456'

并且两次都失败且没有错误:

    def test_hash_autouse():
        g = Guest(0, 'username', 'password', 'name', 'email')
>       assert g.password == '123456'
E       AssertionError: assert 'pbkdf2:sha25...b4faf022af81c' == '123456'
E         - pbkdf2:sha256:150000$M1zININg$559128a3793e155eb472d1c1e7f686b7c8cb802a296d6a8b38ab4faf022af81c
E         + 123456

还有我的客座模特:

from dataclasses import dataclass

from flask_login import UserMixin
from flask_pymongo import ObjectId
from werkzeug.security import check_password_hash, generate_password_hash

@dataclass
class Guest(UserMixin):
    _id: ObjectId
    username: str
    _password: str
    name: str
    email: str

    def __post_init__(self):
        # Sets password hash on user registration
        # When class is reinstantiated from DB password is not re-hashed
        if "pbkdf2:sha256:" not in self._password:
            self._password = generate_password_hash(self._password)

    @property
    def password(self):
        return self._password

    @password.setter
    def password(self, val):
        self._password = generate_password_hash(val)

    @property
    def id(self):
        return self._id

    @id.setter
    def id(self, val):
        self._id = val

    def check_password(self, password):
        return check_password_hash(self._password, password)

有什么想法吗?谢谢。

最佳答案

由于 monkeypatch.setattr 的工作方式与 unittest.mock.patch.object 类似,因此 advice applies

由此而来:

[monkeypatch.setattr] works by (temporarily) changing the object that a name points to with another one. There can be many names pointing to any individual object, so for patching to work you must ensure that you patch the name used by the system under test.

在这种情况下,from 导入引入了一个新名称,指向您尝试修补的对象,因此您需要确保在该模块中修补它

您有两种选择来解决此问题,要么在应用程序中使用 import werkzeug.security 并保持测试代码相同,要么调整补丁以将功能修补到模型模块之外

请注意,from 导入基本上等同于:

  1. 使模块在 sys.modules 中全局可用
  2. from module_name import imported_name [as asname] 分配 asname = getattr(sys.modules[module_name], imported_name)

关于python - 用于测试的模拟密码哈希,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58864006/

相关文章:

python - 合并文件权限

python - 如何使用 Insert/Modify/Remove 将 dynamodb 设计为 Elastic search

python - 如何在 Vim 中一次注释选定的代码块?

python - 如何使用 pytest 禁用测试?

python - 当 pytest 运行目录中的所有测试时,它如何决定最后运行哪个测试?

python - Python 中的 Json : Receive/Check duplicate key error

python - HeartBleed python 测试脚本

python - 几个模块的 Pytest init 设置

python - Pytest 的 "caplog" fixture 的类型提示是什么?