-
Notifications
You must be signed in to change notification settings - Fork 1
Testing
Unit testing can be used to test functions that do not have any external dependencies such as database connections. These tests should be fast and simple to implement.
Mocking can be used if we want to unit test a function that calls an external dependency, or a context sensitive method such as Date
methods which generate the current datetime.
Unit tests can be run with the following command:
npm run test:unit
This will run all tests found in the tests/unit
directory.
// tests/unit/math.test.js
describe('example math util test', () => {
it('2 + 2 = 4', () => {
expect(2 + 2).toEqual(4);
});
});
In order to test controllers without the use of UI, we can use integration tests using Jest and a test database. A test database, separate from the real development database will be needed in order to run these tests.
If you follow the Docker setup, this test database should already be created as a separate container running in port 3307.
The DATABASE_URL
environment variable will be replaced using the content from .env.test.integration
. Modify this file if you need to use another database for testing, by default it uses the Docker test database container.
In order to start integration tests, run the following command:
npm run test:integration
This will run the following steps:
- Migrate the test database with the latest schema
- Add data to the test database using local fixture files before any test runs (see
tests/setup.js
) - Run tests found in
tests/integration
directory - Delete all data set up in step 2
ℹ️ You can also use
npm run test:integration:watch
, this will re-run tests on file save and skip Step 1 from the previous steps. This will be more efficient for debugging, just make sure to migrate at least once if there are new migrations as these will not run with this command.
⚠️ Integration tests are run sequentially and are generally slower to run than unit tests since they communicate frequently with a test database.
Sample data used for testing can be found in tests/fixtures
. These are JSON files that are used in tests/setup.js
to load the test database with sample data. If you need to add more sample data, or modify the current ones when you add new fields to a table, you can modify this fixture directory.
In this sample test we will test the listLocations
function from the locations
controller.
// app/controllers/locations.js
import { db } from "~/utils/db.server"
export const listLocations = async () => {
const locations = await db.Locations.findMany({
orderBy: {
name: 'asc',
}
});
return locations;
};
// tests/integration/controllers/location.test.js
import { listLocations } from "../../../app/controllers/locations";
describe("location controllers", () => {
describe("listLocations", () => {
it("returns list of locations ordered by name", async () => {
const expected = [
{ name: 'All', code: 'ALL' },
{ name: 'Bangkok', code: 'BNK' },
{ name: 'Guadalajara', code: 'GDL' },
{ name: 'Ho Chi Minh', code: 'HCMC' },
{ name: 'Mexico City', code: 'CDMX' },
{ name: 'New York', code: 'NYC' },
{ name: 'Queretaro', code: 'QRO' },
{ name: 'San Francisco', code: 'SF' }
];
const locations = await listLocations();
expect(locations).toBeDefined();
expect(locations).toEqual(expected);
})
});
});
Before this test runs, data is loaded into the Locations database table using tests/fixtures/locations.json
file. We can use this to declare what we expect to get and what is actually returned by the controller.
In this case, we expect to get the same list of locations from the fixtured but ordered in alphabetical order by their name.
📑 You can learn more about Jest syntax in this documentation.
Feel free to update this wiki to help other developers