简体   繁体   English

FASTAPI 测试数据库不创建数据库

[英]FASTAPI Testing Database not creating db

I'm trying to test my FASTAPI app.我正在尝试测试我的 FASTAPI 应用程序。 Seems to me, all settings are correct.在我看来,所有设置都是正确的。

test_users.py测试用户.py

engine = create_engine(
    f"postgresql"
    f"://{settings.database_username}"
    f":{settings.database_password}"
    f"@{settings.database_hostname}"
    f":{settings.database_port}"
    f"/test_{settings.database_name}"
    )
TestingSessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base.metadata.create_all(bind=engine)

def override_get_db():
    try:
        db = TestingSessionLocal()
        yield db
    finally:
        db.close()

app.dependency_overrides[get_db] = override_get_db

client = TestClient(app)


def test_create_user():
    response = client.post(
        "/users/",
        json={"email": "nikita@gmail.com", "password": "password"}
    )
    new_user = schemas.UserOutput(**response.json())

    assert response.status_code == 201
    assert new_user.email == "nikita@gmail.com"

When i run pytest i recive this error当我运行pytest时,我收到此错误

sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) connection to server at "localhost" (::1), port 5432 failed: FATAL:  database "test_social_media_api" does not exist

Why code is not creating the db?为什么代码没有创建数据库?

With engine = create_engine("postgresql://...") you define a connection to an existing PostgreSql database.使用engine = create_engine("postgresql://...")定义与现有 PostgreSql 数据库的连接。 And with Base.metadata.create_all(bind=engine) you create the tables - according to your models - in the existing database.使用Base.metadata.create_all(bind=engine)您可以根据您的模型在现有数据库中创建表。

So the code that you written does not create a database, it expects that you give it an already existing database.所以你写的代码不会创建数据库,它希望你给它一个已经存在的数据库。

And that has to do with PostgreSQL itself.这与 PostgreSQL 本身有关。 PostgreSQL runs as a server, and a PostgreSQL server can run multiple databases. PostgreSQL作为服务器运行,PostgreSQL服务器可以运行多个数据库。 And each database has to be created explicitly.并且必须显式创建每个数据库。 Just telling SQLAlchemy the connection string is not enough.仅仅告诉 SQLAlchemy 连接字符串是不够的。

It's possible to create a new database from Python itself by connecting to the PostgreSQL server (see https://www.tutorialspoint.com/python_data_access/python_postgresql_create_database.htm ), or alternatively you can create it manually before you run your script.可以通过连接到 PostgreSQL 服务器从 Python 本身创建一个新数据库(参见https://www.tutorialspoint.com/python_data_access/python_postgresql_create_database.htm ),或者您可以在运行脚本之前手动创建它。 Eg by running CREATE DATABASE databasename;例如,通过运行CREATE DATABASE databasename; inside psql (or any other database tool).psql (或任何其他数据库工具)中。

However if you want to test using a running database, I would suggest using testcontainers .但是,如果您想使用正在运行的数据库进行测试,我建议您使用testcontainers They will spawn a new PostgreSQL server with an empty database everytime you run the tests.每次运行测试时,它们都会生成一个新的 PostgreSQL 服务器和一个空数据库。


Notice, that the example from the FastAPI documentation works differently.请注意,FastAPI 文档中的示例工作方式不同。 They just use他们只是用

SQLALCHEMY_DATABASE_URL = "sqlite:///./test.db"
engine = create_engine(
    SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
Base.metadata.create_all(bind=engine)

which creates the database.创建数据库。 This works, because SQLite doesn't run as a server.这有效,因为 SQLite 不作为服务器运行。 It's just one file that represents the full database, and if the file doesn't exist, the sqlite database adapter will assume that the database is just empty, and create a new file for you.它只是代表完整数据库的一个文件,如果该文件不存在,sqlite 数据库适配器将假定数据库只是空的,并为您创建一个新文件。 PostgreSQL doesn't work like this though. PostgreSQL 虽然不是这样工作的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM