Flask+ Dependency-injecter+pytest 写测试类

最近在使用这几个在做项目,因为第一次用这个,所以不免有些问题。总结下踩的坑

1.测试类位置

首先测试类约定会放在tests里面,不然有可能发生引入包的问题,会报错某些包找不到。

2. 测试类依赖注入

这里我就用的真实的数据库操作,但是我用了一个专门为测试写的事务管理,所有操作都不会commit而是会rollback,相当于一个内存数据库了,只会在内存里面,不会提交,你也可以直接用内存数据库或者mock,

# tests/test_app.py
import pytest
from main.application import create_app
from main.config.database_config import DatabaseConfig
from main.containers import Container
from dependency_injector.wiring import inject, Provide
from main.services.common_service.db_access.domain.user import User
from main.services.common_service.db_access.service.user_service import UserService
from dependency_injector.providers import Factory
from main.services.common_service.db_access.repository.impl.user_repository_impl import UserRepositoryImpl#获取app
@pytest.fixture
def app():app = create_app()with app.app_context():yield app
#获取user_service
@pytest.fixture
def user_service(app):with app.app_context():user_repo=UserRepositoryImpl()db=app.container.db()yield UserService(user_repository=user_repo,session_factory=db.force_rowback_session)#测试方法,需要传入user_serivice,会从上面加了@pytest.fixture注解获取同名方法进行注入
def test_create_user(user_service):user=user_service.create_user()assert user is not None

我的userservice需要传入两个参数,一个是repo的实现类,一个是sqla的session

"""Containers module."""import os
from dependency_injector import containers, providersfrom main.config.database_config import DatabaseConfigclass Container(containers.DeclarativeContainer):# wiring_config = containers.WiringConfiguration(auto_wire=True)wiring_config = containers.WiringConfiguration(packages=["main.config", "main.web.controller","main"])config_path = os.path.join(os.path.dirname(__file__), "../config.yml")config = providers.Configuration(yaml_files=[config_path])db=providers.Singleton(DatabaseConfig,db_url=config.db.url)

有个很重要的一点就是
这里如果写成这样过的话,启动项目是没有什么问题。但是测试类的时候就会加载不到,就会导致需要config的类加载不到你需要的配置。

config = providers.Configuration(yaml_files=['config.yml'])

所以必须写成这样

config_path = os.path.join(os.path.dirname(__file__), "../config.yml")
config = providers.Configuration(yaml_files=[config_path])

事务控制 

"""Database module."""from contextlib import contextmanager, AbstractContextManager
from typing import Callablefrom sqlalchemy import create_engine, orm,event
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session
from datetime import datetimefrom main.services.common_service.db_access.domain.common_field_entity import CommonEntity
Base = declarative_base()class DatabaseConfig:def __init__(self, db_url: str) -> None:self._engine = create_engine(db_url, echo=True)self._session_factory = orm.scoped_session(orm.sessionmaker(autocommit=False,autoflush=False,expire_on_commit=False,bind=self._engine,),)def create_database(self) -> None:Base.metadata.create_all(self._engine)@contextmanagerdef session(self) -> Callable[..., AbstractContextManager[Session]]:session: Session = self._session_factory()try:yield sessionexcept Exception:session.rollback()raiseelse:if session._transaction.is_active:session.commit()session.close()@contextmanager#专门负责测试类的回滚操作,不论任何情况,都进行回滚操作def force_rowback_session(self) -> Callable[..., AbstractContextManager[Session]]:session: Session = self._session_factory()try:yield sessionexcept Exception:session.rollback()raiseelse:session.rollback()session.close()@event.listens_for(CommonEntity, 'before_insert', propagate=True)def before_insert_listener(self, mapper, target):# 在创建时自动更新 created_dt,versiontarget.created_dt = datetime.now()target.created_by = 'MAAS'target.version = 1@event.listens_for(CommonEntity, 'before_update', propagate=True)def before_update_listener(self, mapper, target):# 在更新时自动更新 updated_dt,versiontarget.updated_dt = datetime.now()target.updated_by = 'MAAS'target.version += 1

运行测试

就直接到文件目录,执行pytest命令就可以了,没有pytest就pip install 一下就行了

pytest xxx.py

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/344102.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥杯单片机组备赛——蜂鸣器和继电器的基本控制

文章目录 一、蜂鸣器和继电器电路介绍二、题目与答案2.1 题目2.2 答案2.3 重点函数解析 一、蜂鸣器和继电器电路介绍 可以发现两个电路一端都接着VCC,所以我们只要给另一端接上低电平就可以让蜂鸣器和继电器进行工作。与操作LED类似,只不过换了一个74HC5…

小白进公司快速熟悉环境和代码的方法

1.企业开发模式 企业开发模式里,我们的项目模块可能非常多此时我们是不能将所有模块都拉取到本地的,主要原因如下: 我们很可能并没有全部工程代码的权限 微服务集群部署非常复杂,本地部署成本太高 微服务模块众多,本…

vue3用elementplus table渲染二维码使用方法

TOC 在Vue3中实现二维码生成需要使用第三方库来处理生成二维码的逻辑,常用的库有 qrcode和 vue-qrcode,这篇文章主要介绍了在Vue3中使用vue-qrcode库实现二维码生成,需要的朋友可以参考下 本文主要介绍在Vue3中使用qrcode库实现二维码生成的方法。 在Vue3中实现二维码生成需…

酚醛胶面建筑模板 — 广西厂家直销,质保可靠

在现代建筑行业中,选择高质量的建筑板材对于确保施工质量和工程安全至关重要。广西厂家直销的酚醛胶面建筑板,以其卓越的质量和可靠的质保,成为了建筑行业的优选材料。 产品特性 卓越的耐候性:我们的酚醛胶面建筑板采用高品质酚醛…

C++力扣题目106,105--中序和后序,前序和中序遍历构造二叉树

106.从中序与后序遍历序列构造二叉树 力扣题目链接(opens new window) 根据一棵树的中序遍历与后序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 中序遍历 inorder [9,3,15,20,7]后序遍历 postorder [9,15,7,20,3] 返回如下的二叉树&am…

计算机缺失msvcp140.dll的修复教程,教你快速解决dll问题

“针对计算机系统中出现的msvcp140.dll文件丢失问题,小编将详细阐述一系列有效的解决方法。首先,msvcp140.dll是Microsoft Visual C Redistributable Package中的一个关键动态链接库文件,对于许多应用程序的正常运行至关重要。当系统提示该文…

Minitab的单因子方差分析的结果

单因子方差分析概述 当有一个类别因子和一个连续响应并且想要确定两个或多个组的总体均值是否存在差异时,可使用 单因子方差分析。如果经检验,发现至少有一组存在差异,请使用单因子方差分析中的比较对话框来标识存在显著差异的组对。 例如&…

Win10安装配置Redis,修改密码

一、下载Redis tporadowski 提供了 支持 Windows平台的 Redis 安装包,目前仍在维护,目前最新版本是 5.0.14,更新速度跟Redis官网也相差好几个大版本。 下载地址:https://github.com/tporadowski/redis/releases 二、Redis 安装 …

MATLAB - 卫星自旋的模型参考自适应控制(MRAC)

系列文章目录 前言 本例展示了如何使用模型参考自适应控制 (MRAC) 控制卫星自旋,使未知控制系统与理想参考模型相匹配。卫星系统在 Simulink 中建模,MRAC 控制器使用 Simulink Control Design™ 软件提供的模型参考自适应控制模块实现。 一、卫星旋转控…

CCF模拟题 202309-2 坐标变换(其二)

问题描述 试题编号: 202309-2 试题名称: 坐标变换(其二) 时间限制: 1.0s 内存限制: 512.0MB 问题描述: 对于平面直角坐标系上的坐标 (x,y),小 P 定义了如下两…

仓储|仓库管理水墨屏RFID电子标签2.4G基站CK-RTLS0501G功能说明与安装方式

随着全球智能制造进度的推进以及物流智能化管理水平的升级,行业亟需一种既能实现RFID批量读取、又能替代纸质标签在循环作业、供应链管理以及实现动态条码标签显示的产品。在此种行业需求背景下,我是适时推出了基于墨水屏显示技术的VT系列可视化超高频标…

Office Tool Plus v10.6.2.0绿色版

软件介绍 Office Tool Plus(简称OTP)是一款微软Office办公软件下载、安装、管理的辅助增强工具。它可以快速自定义部署,在线下载安装 Office 的各个版本,也可以通过已有的离线安装文件来部署Office镜像,同时在安装过程…