I am starting to implement unit tests in a Vapor 4 project but the users
postgres table is not being deleted/created after each tests. It works only for 1 test before it crashes them all.
Even though I am not implementing any tests, the compiler stop with this error:
caught error: "previousError(server: table "users" does not exist (DropErrorMsgNonExistent))"
My database is running with PostgreSQL in a Docker container. When I delete this container manually and run the tests again, there is no error. When I run it a second time, the error comes back.
Why is my table not being deleted after each tests?
This is my testing file, I have implemented a simple test to try out the plumbing:
import XCTVapor
@testable import App
class BaseXCTestCase: XCTestCase {
var app: Application!
override func setUpWithError() throws {
try super.setUpWithError()
app = Application(.testing)
try configure(app). // The error is caught here.
}
override func tearDownWithError() throws {
app.shutdown()
try super.tearDownWithError()
}
// This test crashes if everything goes well, but it
// doesn't even run as the crashes appears in configure.swift.
func test_zero() {
XCTFail("Tests not yet implemented")
}
}
This is my users
table:
import Fluent
struct UserModelMigration_v1_0_0: Migration {
func prepare(on database: Database) -> EventLoopFuture<Void> {
database.schema("users")
.id()
.field("email", .string, .required)
.field("password", .string, .required)
.field("appleID", .string)
.unique(on: "email")
.create()
}
func revert(on database: Database) -> EventLoopFuture<Void> {
database.schema("users").delete()
}
}
This is a part of my configure.swift
file where I setup the migration for the tests:
import Fluent
import FluentPostgresDriver
import Vapor
public func configure(_ app: Application) throws {
// MARK: Database
let databaseName: String
let databasePort: Int
if app.environment == .testing {
databaseName = "db_testing"
databasePort = 5434
}
else {
databaseName = "db_development"
databasePort = 5433
}
app.databases.use(.postgres(
hostname: "localhost",
port: databasePort,
username: "username",
password: "password",
database: databaseName
), as: .psql)
// MARK: Migrations
app.migrations.add(UserModelMigration_v1_0_0())
// MARK: Clear Database
if app.environment == .testing {
try app.autoRevert().wait()
}
if !app.environment.isRelease {
try app.autoMigrate().wait()
}
}
There are also two files where I added code to run the tests in the Docker container.
file: docker-compose-testing.yml
version: '3'
services:
serverside-app:
depends_on:
- postgres
build:
context: .
dockerfile: testing.Dockerfile
environment:
- DATABASE_HOST=postgres
- DATABASE_PORT=5434
postgres:
image: "postgres"
environment:
- POSTGRES_DB=db_testing
- POSTGRES_USER=username
- POSTGRES_PASSWORD=password
file: testing.Dockerfile
FROM swift:5.3
WORKDIR /package
COPY . ./
CMD ["swift", "test", "--enable-test-discovery"]
Your revert will fail if the table doesn't exist.
Changing it to try? app.autoRevert().wait()
and your auto-migration to try? app.autoMigrate().wait()
will ignore any errors.