如何在方法中测试单个调用?

2024-05-19 05:52:01 发布

您现在位置:Python中文网/ 问答频道 /正文

在下面的代码中,我想测试一下,如果config_dir不存在,它将被创建

    def __init__(
        self, config_dir: pathlib.Path = pathlib.Path().home() / ".config" / "moe",
    ):
        """Read configuration.

        Args:
            config_dir: Path of the configuration directory.
        """
        self.config_dir = config_dir

        if not self.config_dir.exists():
            self.config_dir.mkdir(parents=True)

        self.db_path: pathlib.Path = self.config_dir / "library.db"

        # initialize db
        engine = sqlalchemy.create_engine("sqlite:///" + str(self.db_path))
        library.Session.configure(bind=engine)
        library.Base.metadata.create_all(engine)  # create tables if they don't exist

然而,我似乎不知道如何测试这部分代码。我试过了

    def test_config_dir_dne(self, mocker):
        """We should create the config directory if it doesn't exist."""
        fake_path = mocker.Mock()
        moe.config.Config(fake_path)

        fake_path.mkdir.assert_called_once_with(parents=True)

但是,pathlib不喜欢我在mock中使用特定的join操作符

>       self.db_path: pathlib.Path = self.config_dir / "library.db"
E       TypeError: unsupported operand type(s) for /: 'Mock' and 'str'

此外,我并不真正关心这部分测试代码,也不希望在最后创建引擎

我如何在不运行任何其他代码的情况下测试检查mkdirs是否在我的fake_path上被调用


Tags: path代码selfconfigdbifdefcreate
2条回答

__init__添加一个附加参数,该函数用于初始化数据库。默认情况下,您将使用类本身提供的函数

def __init__(
    self,
    config_dir: pathlib.Path = pathlib.Path().home() / ".config" / "moe",
    db_initializer=None
):
    """Read configuration.

    Args:
        config_dir: Path of the configuration directory.
    """
    self.config_dir = config_dir

    if not self.config_dir.exists():
        self.config_dir.mkdir(parents=True)

    self.db_path: pathlib.Path = self.config_dir / "library.db"

    if db_initializer is None:
        db_intializer = self._init_db

    db_initializer(self.dp_path)

@staticmethod
def _init_db(p):
    engine = sqlalchemy.create_engine("sqlite:///" + str(p))
    library.Session.configure(bind=engine)
    library.Base.metadata.create_all(engine)

当您测试该函数时,您将传递一个不执行任何操作的函数

def test_config_dir_dne(self, mocker):
        """We should create the config directory if it doesn't exist."""
        fake_path = mocker.Mock()
        moe.config.Config(fake_path, lambda p: None)

        fake_path.mkdir.assert_called_once_with(parents=True)

这里有三种通用方法:

  1. 模仿更多。具体来说,您可以修补pathlib.Pathsqlalchemy.create_engine以及您不想测试的所有内容

  2. 使用依赖项注入,这样您就可以在不进行修补的情况下进行模拟。让构造函数获取抽象接口,然后让您的测试通过这些接口的虚拟版本

  3. 重新构造代码,使每个要单独测试的单元都有自己的功能。将要测试的逻辑(创建config dir)放入它自己的函数中,然后独立于构造函数对该函数进行单元测试

相关问题 更多 >

    热门问题