我正在阅读从零到生产的书,书的第74-76页谈到了测试函数在运行多次时如何失败,因为每次我们运行cargo test
测试函数都会运行应用程序,并且应用程序中有一个插入查询,所以每次我们运行测试时,调用该应用程序,执行插入查询,并插入相同的值,这由于唯一键约束而导致错误。本书提供了一个解决方案
1.创建具有唯一名称的新逻辑数据库
2.run迁移到此数据库
//! tests/health_check.rs
use std::net::TcpListener;
use sqlx::{PgConnection, PgPool, Connection, Executor};
use zero2prod::configuration::{get_configuration, DatabaseSettings};
use zero2prod::startup::run;
use uuid::Uuid;
pub struct TestApp {
pub address: String,
pub pool: PgPool,
}
async fn spawn_app() -> TestApp {
let listener = TcpListener::bind("127.0.0.1:0").expect("failed to bind to the port");
let port = listener.local_addr().unwrap().port();
let address = format!("http://127.0.0.1:{}", port);
let mut configuration = get_configuration().expect("failed to read configuration");
configuration.database.database_name = Uuid::new_v4().to_string();
let connection_pool = PgPool::connect(&configuration.database.connection_string()).await.expect("failed to connect to postgres");
let server = run(listener, connection_pool.clone()).expect("failed to bind to address");
let _ = tokio::spawn(server);
TestApp{
address,
pool: connection_pool,
}
}
字符串
本书随后进行了以下修改:
//! tests/health_check.rs
let mut configuration = get_configuration().expect("Failed to read configuration.");
configuration.database.database_name = Uuid::new_v4().to_string();
let connection_pool = PgPool::connect(&configuration.database.connection_string())
.await
.expect("Failed to connect to Postgres.");
x
//! src/configuration.rs
// [...]
impl DatabaseSettings {
pub fn connection_string(&self) -> String {
format!(
"postgres://{}:{}@{}:{}/{}",
self.username, self.password, self.host, self.port, self.database_name
)
}
pub fn connection_string_without_db(&self) -> String {
format!(
"postgres://{}:{}@{}:{}",
self.username, self.password, self.host, self.port
)
}
}
//! tests/health_check.rs
// [...]
use sqlx::{Connection, Executor, PgConnection, PgPool};
use zero2prod::configuration::{get_configuration, DatabaseSettings};
async fn spawn_app() -> TestApp {
// [...]
let mut configuration = get_configuration().expect("Failed to read configuration.");
configuration.database.database_name = Uuid::new_v4().to_string();
let connection_pool = configure_database(&configuration.database).await;
// [...]
}
pub async fn configure_database(config: &DatabaseSettings) -> PgPool {
// Create database
let mut connection = PgConnection::connect(&config.connection_string_without_db())
.await
.expect("Failed to connect to Postgres");
connection
.execute(format!(r#"CREATE DATABASE "{}";"#, config.database_name).as_str())
.await
.expect("Failed to create database.");
// Migrate database
let connection_pool = PgPool::connect(&config.connection_string())
.await
.expect("Failed to connect to Postgres.");
sqlx::migrate!("./migrations")
.run(&connection_pool)
.await
.expect("Failed to migrate the database");
connection_pool
}
的字符串
我不明白最后一个函数configure_database
的作用,以及添加该函数如何解决问题
1条答案
按热度按时间u3r8eeie1#
如果他不创建一个新的数据库,并使用相同的数据库,他将无法做全面的测试,因为他们的数据是从以前的测试。我也读过这本书,他正在使用Docker容器来实现Postgress。而不是创建一个新的随机数据库,他也可以删除docker容器并创建一个新的,每次他运行测试时,他可以使用常量数据库名称。如果你问我的话,这是个让人头疼的过程