Struct TestDatabase

Source
pub struct TestDatabase { /* private fields */ }
Available on crate feature db only.
Expand description

A test database.

This is used to create a separate database for testing and run migrations on it.

§Examples

use cot::test::{TestDatabase, TestRequestBuilder};

let mut test_database = TestDatabase::new_sqlite().await?;
let request = TestRequestBuilder::get("/")
    .database(test_database.database())
    .build();

// do something with the request

test_database.cleanup().await?;

Implementations§

Source§

impl TestDatabase

Source

pub async fn new_sqlite() -> Result<Self>

Create a new in-memory SQLite database for testing.

§Errors

If the database could not have been created.

§Examples
use cot::test::{TestDatabase, TestRequestBuilder};

let mut test_database = TestDatabase::new_sqlite().await?;
let request = TestRequestBuilder::get("/")
    .database(test_database.database())
    .build();

// do something with the request

test_database.cleanup().await?;
Source

pub async fn new_postgres(test_name: &str) -> Result<Self>

Create a new PostgreSQL database for testing and connects to it.

The database URL is read from the POSTGRES_URL environment variable. Note that it shouldn’t include the database name — the function will create a new database for the test by connecting to the postgres database. If no URL is provided, it defaults to postgresql://cot:cot@localhost.

The database is created with the name test_cot__{test_name}. Make sure that test_name is unique for each test so that the databases don’t conflict with each other.

The database is dropped when self.cleanup() is called. Note that this means that the database will not be dropped if the test panics.

§Errors

Returns an error if a database connection (either to the test database, or postgres maintenance database) could not be established.

Returns an error if the old test database could not be dropped.

Returns an error if the new test database could not be created.

§Examples
use cot::test::{TestDatabase, TestRequestBuilder};

let mut test_database = TestDatabase::new_postgres("my_test").await?;
let request = TestRequestBuilder::get("/")
    .database(test_database.database())
    .build();

// do something with the request

test_database.cleanup().await?;
Source

pub async fn new_mysql(test_name: &str) -> Result<Self>

Create a new MySQL database for testing and connects to it.

The database URL is read from the MYSQL_URL environment variable. Note that it shouldn’t include the database name — the function will create a new database for the test by connecting to the mysql database. If no URL is provided, it defaults to mysql://root:@localhost.

The database is created with the name test_cot__{test_name}. Make sure that test_name is unique for each test so that the databases don’t conflict with each other.

The database is dropped when self.cleanup() is called. Note that this means that the database will not be dropped if the test panics.

§Errors

Returns an error if a database connection (either to the test database, or MySQL maintenance database) could not be established.

Returns an error if the old test database could not be dropped.

Returns an error if the new test database could not be created.

§Examples
use cot::test::{TestDatabase, TestRequestBuilder};

let mut test_database = TestDatabase::new_mysql("my_test").await?;
let request = TestRequestBuilder::get("/")
    .database(test_database.database())
    .build();

// do something with the request

test_database.cleanup().await?;
Source

pub fn with_auth(&mut self) -> &mut Self

Add the default Cot authentication migrations to the test database.

This is useful if you want to test something that requires authentication.

§Examples
use cot::test::{TestDatabase, TestRequestBuilder};

let mut test_database = TestDatabase::new_sqlite().await?;
test_database.with_auth().run_migrations().await;

let request = TestRequestBuilder::get("/")
    .with_db_auth(test_database.database())
    .await
    .build();

// do something with the request

test_database.cleanup().await?;
Source

pub fn add_migrations<T: DynMigration + Send + Sync + 'static, V: IntoIterator<Item = T>>( &mut self, migrations: V, ) -> &mut Self

Add migrations to the test database.

§Examples
use cot::test::{TestDatabase, TestMigration};

let mut test_database = TestDatabase::new_sqlite().await?;

test_database.add_migrations(vec![TestMigration::new(
    "auth",
    "create_users",
    vec![],
    vec![],
)]);
Source

pub async fn run_migrations(&mut self) -> &mut Self

Run the migrations on the test database.

§Panics

Panics if the migration engine could not be initialized or if the migrations could not be run.

§Examples
use cot::test::{TestDatabase, TestMigration};

let mut test_database = TestDatabase::new_sqlite().await?;
test_database.add_migrations(vec![TestMigration::new(
    "auth",
    "create_users",
    vec![],
    vec![],
)]);

test_database.run_migrations().await;
Source

pub fn database(&self) -> Arc<Database>

Get the database.

§Examples
use cot::test::{TestDatabase, TestRequestBuilder};

let database = TestDatabase::new_sqlite().await?;

let request = TestRequestBuilder::get("/")
    .database(database.database())
    .build();
Source

pub async fn cleanup(&self) -> Result<()>

Cleanup the test database.

This removes the test database and closes the connection. Note that this means that the database will not be dropped if the test panics, nor will it be dropped if you don’t call this function.

§Errors

Returns an error if the database could not be closed or if the database could not be dropped.

§Examples
use cot::test::TestDatabase;

let mut test_database = TestDatabase::new_sqlite().await?;
test_database.cleanup().await?;

Methods from Deref<Target = Database>§

Source

pub async fn close(&self) -> Result<()>

Closes the database connection.

This method should be called when the database connection is no longer needed. The connection is closed and the resources are released.

§Errors

This method can return an error if the connection to the database could not be closed gracefully, for instance because the connection has already been dropped.

§Examples
use cot::db::Database;

#[tokio::main]
async fn main() {
    let db = Database::new("sqlite::memory:").await.unwrap();
    db.close().await.unwrap();
}
Source

pub async fn insert<T: Model>(&self, data: &mut T) -> Result<()>

Inserts a new row into the database.

§Errors

This method can return an error if the row could not be inserted into the database, for instance because the migrations haven’t been applied, or there was a problem with the database connection.

Source

pub async fn insert_or_update<T: Model>(&self, data: &mut T) -> Result<()>

Inserts a new row into the database, or updates it if a row with the same primary key already exists.

§Errors

This method can return an error if the row could not be inserted into the database, for instance because the migrations haven’t been applied, or there was a problem with the database connection.

Source

pub async fn update<T: Model>(&self, data: &mut T) -> Result<()>

Updates an existing row in a database.

§Errors

This method can return an error if the row could not be updated in the database, for instance because the migrations haven’t been applied, or there was a problem with the database connection.

This method can return an error if the row with the given primary key could not be found in the database.

Source

pub async fn query<T: Model>(&self, query: &Query<T>) -> Result<Vec<T>>

Executes the given query and returns the results converted to the model type.

§Errors

This method can return an error if the query is invalid.

This method can return an error if the data in the database is not compatible with the model (usually meaning the migrations haven’t been generated or applied).

Can return an error if the database connection is lost.

Source

pub async fn get<T: Model>(&self, query: &Query<T>) -> Result<Option<T>>

Returns the first row that matches the given query. If no rows match the query, returns None.

§Errors

This method can return an error if the query is invalid.

This method can return an error if the model doesn’t exist in the database (usually meaning the migrations haven’t been generated or applied).

Can return an error if the database connection is lost.

Source

pub async fn exists<T: Model>(&self, query: &Query<T>) -> Result<bool>

Returns whether a row exists that matches the given query.

§Errors

This method can return an error if the query is invalid.

This method can return an error if the model doesn’t exist in the database (usually meaning the migrations haven’t been generated or applied).

Can return an error if the database connection is lost.

Source

pub async fn delete<T: Model>( &self, query: &Query<T>, ) -> Result<StatementResult>

Deletes all rows that match the given query.

§Errors

This method can return an error if the query is invalid.

This method can return an error if the model doesn’t exist in the database (usually meaning the migrations haven’t been generated or applied).

Can return an error if the database connection is lost.

Source

pub async fn raw(&self, query: &str) -> Result<StatementResult>

Executes a raw SQL query.

§Errors

This method can return an error if the query is invalid.

Can return an error if the database connection is lost.

§Examples
use cot::db::Database;

let db = Database::new("sqlite::memory:").await?;
db.raw("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)")
    .await?;
Source

pub async fn raw_with( &self, query: &str, values: &[&dyn ToDbValue], ) -> Result<StatementResult>

Executes a raw SQL query with parameters.

§Errors

This method can return an error if the query is invalid.

Can return an error if the database connection is lost.

§Examples
use cot::db::Database;

let db = Database::new("sqlite::memory:").await?;
db.raw("CREATE TABLE test (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT)")
    .await?;
db.raw_with("SELECT * FROM test WHERE id = ?", &[&1])
    .await?;

Trait Implementations§

Source§

impl Debug for TestDatabase

Source§

fn fmt(&self, __derive_more_f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Deref for TestDatabase

Source§

type Target = Database

The resulting type after dereferencing.
Source§

fn deref(&self) -> &Self::Target

Dereferences the value.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Fake for T

Source§

fn fake<U>(&self) -> U
where Self: FakeBase<U>,

Source§

fn fake_with_rng<U, R>(&self, rng: &mut R) -> U
where R: Rng + ?Sized, Self: FakeBase<U>,

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoField<Auto<T>> for T

Source§

fn into_field(self) -> Auto<T>

Available on crate feature db only.
Converts the type to the field type.
Source§

impl<P, T> Receiver for P
where P: Deref<Target = T> + ?Sized, T: ?Sized,

Source§

type Target = T

🔬This is a nightly-only experimental API. (arbitrary_self_types)
The target type on which the method may be called.
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<A, B, T> HttpServerConnExec<A, B> for T
where B: Body,

Source§

impl<T> MaybeSendSync for T