Python 模拟密码哈希以进行测试

Python 模拟密码哈希以进行测试,python,pytest,Python,Pytest,我试图通过模拟大多数测试的密码散列来加速我的flask应用程序的测试。我在windows上使用pytest和Python3.8 我尝试了以下方法: import pytest import werkzeug.security @pytest.fixture(autouse=True) def mock_password_hash(monkeypatch, request): if "no_mock_password_hash" in request.keywords:

我试图通过模拟大多数测试的密码散列来加速我的flask应用程序的测试。我在windows上使用pytest和Python3.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)

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

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类似

由此:

[monkeypatch.setattr]的工作原理是(暂时)用另一个名称更改名称指向的对象。可以有许多名称指向任何单个对象,因此为了使修补工作正常进行,必须确保修补被测系统使用的名称

在本例中,来自导入的
引入了一个新名称,指向您试图修补的对象,因此您需要确保在该模块中修补它

要解决此问题,您有两种选择,一种是在应用程序中使用
import werkzeug.security
,并保持测试代码不变,另一种是调整修补程序以修补模型模块之外的功能

请注意,
导入的
本质上等同于:

  • 使模块在
    sys.modules
  • 分配
    asname=getattr(sys.modules[module\u name],imported\u name)
    from module\u name imported\u name[as asname]

  • 与其模仿它,为什么不在测试模式下将循环数减少到1?
    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)