mirror of https://github.com/docker/docs.git
Add 2 New Use Case Guides - Pre-Seeding database and WireMock (#20968)
* Added a use case guide for Pre-seeding database * Fixed formatting * Fixed vale linting * Added WireMock use case guide * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Removed psql instructions under the prerequisite * Removed the statement that ask user to enter password * Removed Windows Tips as we're using command * Modified the volume section * added a note for port mapping * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Removed bold cases * Added instructions for Node and NPM * Moved the index.js file explanation up in step 3 * Added a prerequisite for WireMock * Added list of sections in the inital para * Added missing instructions * Modified wiremock guide * linting and fixes * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * avoid exposing API keys in logs * Fixed formatting * Fixed the result for Wiremock * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/pre-seeding.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Update content/guides/use-case/wiremock.md Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com> * Fixing linting issues --------- Co-authored-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
This commit is contained in:
parent
4b43bed5ce
commit
abdedeac6f
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
After Width: | Height: | Size: 49 KiB |
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
|
@ -0,0 +1,339 @@
|
|||
---
|
||||
description: Pre-seeding database with schema and data at startup for development environment
|
||||
keywords: Pre-seeding, database, postgres, container-supported development
|
||||
title: Pre-seeding database with schema and data at startup for development environment
|
||||
linktitle: Pre-seeding database
|
||||
---
|
||||
|
||||
Pre-seeding databases with essential data and schema during local development is a common practice to enhance the development and testing workflow. By simulating real-world scenarios, this practice helps catch frontend issues early, ensures alignment between Database Administrators and Software Engineers, and facilitates smoother collaboration. Pre-seeding offers benefits like confident deployments, consistency across environments, and early issue detection, ultimately improving the overall development process.
|
||||
|
||||
In this guide, you will learn how to:
|
||||
|
||||
- Use Docker to launch up a Postgres container
|
||||
- Pre-seed Postgres using a SQL script
|
||||
- Pre-seed Postgres by copying SQL files into Docker image
|
||||
- Pre-seed Postgres using JavaScript code
|
||||
|
||||
## Using Postgres with Docker
|
||||
|
||||
The [official Docker image for Postgres](https://hub.docker.com/_/postgres) provides a convenient way to run Postgres database on your development machine. A Postgres Docker image is a pre-configured environment that encapsulates the PostgreSQL database system. It's a self-contained unit, ready to run in a Docker container. By using this image, you can quickly and easily set up a Postgres instance without the need for manual configuration.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
The following prerequisites are required to follow along with this how-to guide:
|
||||
|
||||
- [Docker Desktop](https://www.docker.com/products/docker-desktop/)
|
||||
|
||||
## Launching Postgres
|
||||
|
||||
Launch a quick demo of Postgres by using the following steps:
|
||||
|
||||
1. Open the terminal and run the following command to start a Postgres container.
|
||||
|
||||
This example will launch a Postgres container, expose port `5432` onto the host to let a native-running application to connect to it with the password `mysecretpassword`.
|
||||
|
||||
```console
|
||||
$ docker run -d --name postgres -p 5432:5432 -e POSTGRES_PASSWORD=mysecretpassword postgres
|
||||
```
|
||||
|
||||
2. Verify that Postgres is up and running by selecting the container and checking the logs on Docker Dashboard.
|
||||
|
||||
```plaintext
|
||||
PostgreSQL Database directory appears to contain a database; Skipping initialization
|
||||
|
||||
2024-09-08 09:09:47.136 UTC [1] LOG: starting PostgreSQL 16.4 (Debian 16.4-1.pgdg120+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
|
||||
2024-09-08 09:09:47.137 UTC [1] LOG: listening on IPv4 address "0.0.0.0", port 5432
|
||||
2024-09-08 09:09:47.137 UTC [1] LOG: listening on IPv6 address "::", port 5432
|
||||
2024-09-08 09:09:47.139 UTC [1] LOG: listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
|
||||
2024-09-08 09:09:47.142 UTC [29] LOG: database system was shut down at 2024-09-08 09:07:09 UTC
|
||||
2024-09-08 09:09:47.148 UTC [1] LOG: database system is ready to accept connections
|
||||
```
|
||||
|
||||
3. Connect to Postgres from the local system.
|
||||
|
||||
The `psql` is the PostgreSQL interactive shell that is used to connect to a Postgres database and let you start executing SQL commands. Assuming that you already have `psql` utility installed on your local system, it's time to connect to the Postgres database. Run the following command on your local terminal:
|
||||
|
||||
```console
|
||||
$ docker exec -it postgres psql -h localhost -U postgres
|
||||
```
|
||||
|
||||
You can now execute any SQL queries or commands you need within the `psql` prompt.
|
||||
|
||||
Use `\q` or `\quit` to exit from the Postgres interactive shell.
|
||||
|
||||
## Pre-seed the Postgres database using a SQL script
|
||||
|
||||
Now that you've familiarized yourself with Postgres, it's time to see how to pre-seed it with sample data. In this demonstration, you'll first create a script that holds SQL commands. The script defines the database, and table structure and inserts sample data. Then you will connect the database to verify the data.
|
||||
|
||||
Assuming that you have an existing Postgres database instance up and running, follow these steps to seed the database.
|
||||
|
||||
1. Create an empty file named `seed.sql` and add the following content.
|
||||
|
||||
```sql
|
||||
CREATE DATABASE sampledb;
|
||||
|
||||
\c sampledb
|
||||
|
||||
CREATE TABLE users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(50),
|
||||
email VARCHAR(100) UNIQUE
|
||||
);
|
||||
|
||||
INSERT INTO users (name, email) VALUES
|
||||
('Alpha', 'alpha@example.com'),
|
||||
('Beta', 'beta@example.com'),
|
||||
('Gamma', 'gamma@example.com');
|
||||
```
|
||||
|
||||
The SQL script creates a new database called `sampledb`, connects to it, and creates a `users` table. The table includes an auto-incrementing `id` as the primary key, a `name` field with a maximum length of 50 characters, and a unique `email` field with up to 100 characters.
|
||||
|
||||
After creating the table, the `INSERT` command inserts three users into the `users` table with their respective names and emails. This setup forms a basic database structure to store user information with unique email addresses.
|
||||
|
||||
2. Seed the database.
|
||||
|
||||
It’s time to feed the content of the `seed.sql` directly into the database by using the `<` operator. The command is used to execute a SQL script named `seed.sql` against a Postgres database named `sampledb`.
|
||||
|
||||
```console
|
||||
$ cat seed.sql | docker exec -i postgres psql -h localhost -U postgres -f-
|
||||
```
|
||||
|
||||
Once the query is executed, you will see the following results:
|
||||
|
||||
```plaintext
|
||||
CREATE DATABASE
|
||||
You are now connected to database "sampledb" as user "postgres".
|
||||
CREATE TABLE
|
||||
INSERT 0 3
|
||||
```
|
||||
|
||||
3. Run the following `psql` command to verify if the table named users is populated in the database `sampledb` or not.
|
||||
|
||||
```console
|
||||
$ docker exec -it postgres psql -h localhost -U postgres sampledb
|
||||
```
|
||||
|
||||
You can now run `\l` in the `psql` shell to list all the databases on the Postgres server.
|
||||
|
||||
```console
|
||||
sampledb=# \l
|
||||
List of databases
|
||||
Name | Owner | Encoding | Collate | Ctype | ICU Locale | Locale Provider | Access privileges
|
||||
-----------+----------+----------+------------+------------+------------+-----------------+-----------------------
|
||||
postgres | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc |
|
||||
sampledb | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc |
|
||||
template0 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc | =c/postgres +
|
||||
| | | | | | | postgres=CTc/postgres
|
||||
template1 | postgres | UTF8 | en_US.utf8 | en_US.utf8 | | libc | =c/postgres +
|
||||
| | | | | | | postgres=CTc/postgres
|
||||
(4 rows)
|
||||
```
|
||||
|
||||
To retrieve all the data from the users table, enter the following query:
|
||||
|
||||
```console
|
||||
sampledb=# SELECT * FROM users;
|
||||
id | name | email
|
||||
----+-------+-------------------
|
||||
1 | Alpha | alpha@example.com
|
||||
2 | Beta | beta@example.com
|
||||
3 | Gamma | gamma@example.com
|
||||
(3 rows)
|
||||
```
|
||||
|
||||
Use `\q` or `\quit` to exit from the Postgres interactive shell.
|
||||
|
||||
## Pre-seed the database by bind-mounting a SQL script
|
||||
|
||||
In Docker, mounting refers to making files or directories from the host system accessible within a container. This let you to share data or configuration files between the host and the container, enabling greater flexibility and persistence.
|
||||
|
||||
Now that you have learned how to launch Postgres and pre-seed the database using an SQL script, it’s time to learn how to mount an SQL file directly into the Postgres containers’ initialisation directory (`/docker-entrypoint-initdb.d`). The `/docker-entrypoint-initdb.d` is a special directory in PostgreSQL Docker containers that is used for initializing the database when the container is first started
|
||||
|
||||
Make sure you stop any running Postgres containers (along with volumes) to prevent port conflicts before you follow the steps:
|
||||
|
||||
```console
|
||||
$ docker container stop postgres
|
||||
```
|
||||
|
||||
1. Modify the `seed.sql` with the following entries:
|
||||
|
||||
```sql
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR(50),
|
||||
email VARCHAR(100) UNIQUE
|
||||
);
|
||||
|
||||
INSERT INTO users (name, email) VALUES
|
||||
('Alpha', 'alpha@example.com'),
|
||||
('Beta', 'beta@example.com'),
|
||||
('Gamma', 'gamma@example.com')
|
||||
ON CONFLICT (email) DO NOTHING;
|
||||
```
|
||||
|
||||
2. Create a text file named `Dockerfile` and copy the following content.
|
||||
|
||||
```plaintext
|
||||
# syntax=docker/dockerfile:1
|
||||
FROM postgres:latest
|
||||
COPY seed.sql /docker-entrypoint-initdb.d/
|
||||
```
|
||||
|
||||
This Dockerfile copies the `seed.sql` script directly into the PostgreSQL container's initialization directory.
|
||||
|
||||
|
||||
3. Use Docker Compose.
|
||||
|
||||
Using Docker Compose makes it even easier to manage and deploy the PostgreSQL container with the seeded database. This compose.yml file defines a Postgres service named `db` using the latest Postgres image, which sets up a database with the name `sampledb`, along with a user `postgres` and a password `mysecretpassword`.
|
||||
|
||||
```yaml
|
||||
services:
|
||||
db:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
container_name: my_postgres_db
|
||||
environment:
|
||||
POSTGRES_USER: postgres
|
||||
POSTGRES_PASSWORD: mysecretpassword
|
||||
POSTGRES_DB: sampledb
|
||||
ports:
|
||||
- "5432:5432"
|
||||
volumes:
|
||||
- data_sql:/var/lib/postgresql/data # Persistent data storage
|
||||
|
||||
volumes:
|
||||
data_sql:
|
||||
```
|
||||
|
||||
It maps port `5432` on the host to the container's `5432`, let you access to the Postgres database from outside the container. It also define `data_sql` for persisting the database data, ensuring that data is not lost when the container is stopped.
|
||||
|
||||
It is important to note that the port mapping to the host is only necessary if you want to connect to the database from non-containerized programs. If you containerize the service that connects to the DB, you should connect to the database over a custom bridge network.
|
||||
|
||||
4. Bring up the Compose service.
|
||||
|
||||
Assuming that you've placed the `seed.sql` file in the same directory as the Dockerfile, execute the following command:
|
||||
|
||||
```console
|
||||
$ docker compose up -d --build
|
||||
```
|
||||
|
||||
5. It’s time to verify if the table `users` get populated with the data.
|
||||
|
||||
```console
|
||||
$ docker exec -it my_postgres_db psql -h localhost -U postgres sampledb
|
||||
```
|
||||
|
||||
```sql
|
||||
sampledb=# SELECT * FROM users;
|
||||
id | name | email
|
||||
----+-------+-------------------
|
||||
1 | Alpha | alpha@example.com
|
||||
2 | Beta | beta@example.com
|
||||
3 | Gamma | gamma@example.com
|
||||
(3 rows)
|
||||
|
||||
sampledb=#
|
||||
```
|
||||
|
||||
|
||||
## Pre-seed the database using JavaScript code
|
||||
|
||||
|
||||
Now that you have learned how to seed the database using various methods like SQL script, mounting volumes etc., it's time to try to achieve it using JavaScript code.
|
||||
|
||||
1. Create a .env file with the following:
|
||||
|
||||
```plaintext
|
||||
POSTGRES_USER=postgres
|
||||
POSTGRES_DB_HOST=localhost
|
||||
POSTGRES_DB=sampledb
|
||||
POSTGRES_PASSWORD=mysecretpassword
|
||||
POSTGRES_PORT=5432
|
||||
```
|
||||
|
||||
2. Create a new JavaScript file called seed.js with the following content:
|
||||
|
||||
The following JavaScript code imports the `dotenv` package which is used to load environment variables from an `.env` file. The `.config()` method reads the `.env` file and sets the environment variables as properties of the `process.env` object. This let you to securely store sensitive information like database credentials outside of your code.
|
||||
|
||||
Then, it creates a new Pool instance from the pg library, which provides a connection pool for efficient database interactions. The `seedData` function is defined to perform the database seeding operations.
|
||||
It is called at the end of the script to initiate the seeding process. The try...catch...finally block is used for error handling.
|
||||
|
||||
```plaintext
|
||||
require('dotenv').config(); // Load environment variables from .env file
|
||||
const { Pool } = require('pg');
|
||||
|
||||
// Create a new pool using environment variables
|
||||
const pool = new Pool({
|
||||
user: process.env.POSTGRES_USER,
|
||||
host: process.env.POSTGRES_DB_HOST,
|
||||
database: process.env.POSTGRES_DB,
|
||||
port: process.env.POSTGRES_PORT,
|
||||
password: process.env.POSTGRES_PASSWORD,
|
||||
});
|
||||
|
||||
const seedData = async () => {
|
||||
try {
|
||||
// Drop the table if it already exists (optional)
|
||||
await pool.query(`DROP TABLE IF EXISTS todos;`);
|
||||
|
||||
// Create the table with the correct structure
|
||||
await pool.query(`
|
||||
CREATE TABLE todos (
|
||||
id SERIAL PRIMARY KEY,
|
||||
task VARCHAR(255) NOT NULL,
|
||||
completed BOOLEAN DEFAULT false
|
||||
);
|
||||
` );
|
||||
|
||||
// Insert seed data
|
||||
await pool.query(`
|
||||
INSERT INTO todos (task, completed) VALUES
|
||||
('Watch netflix', false),
|
||||
('Finish podcast', false),
|
||||
('Pick up kid', false);
|
||||
`);
|
||||
console.log('Database seeded successfully!');
|
||||
} catch (err) {
|
||||
console.error('Error seeding the database', err);
|
||||
} finally {
|
||||
pool.end();
|
||||
}
|
||||
};
|
||||
|
||||
// Call the seedData function to run the script
|
||||
seedData();
|
||||
```
|
||||
|
||||
3. Kick off the seeding process
|
||||
|
||||
```console
|
||||
$ node seed.js
|
||||
```
|
||||
|
||||
You should see the following command:
|
||||
|
||||
```plaintext
|
||||
Database seeded successfully!
|
||||
```
|
||||
|
||||
4. Verify if the database is seeded correctly:
|
||||
|
||||
```console
|
||||
$ docker exec -it postgres psql -h localhost -U postgres sampledb
|
||||
```
|
||||
|
||||
```console
|
||||
sampledb=# SELECT * FROM todos;
|
||||
id | task | completed
|
||||
----+----------------+-----------
|
||||
1 | Watch netflix | f
|
||||
2 | Finish podcast | f
|
||||
3 | Pick up kid | f
|
||||
(3 rows)
|
||||
```
|
||||
|
||||
## Recap
|
||||
|
||||
Pre-seeding a database with schema and data at startup is essential for creating a consistent and realistic testing environment, which helps in identifying issues early in development and aligning frontend and backend work. This guide has equipped you with the knowledge and practical steps to achieve pre-seeding using various methods, including SQL script, Docker integration, and JavaScript code.
|
||||
|
|
@ -0,0 +1,292 @@
|
|||
---
|
||||
description: Mocking API services in development and testing with WireMock
|
||||
keywords: WireMock, container-supported development
|
||||
title: Mocking API services in development and testing with WireMock
|
||||
linktitle: Mocking API services with WireMock
|
||||
---
|
||||
|
||||
During local development and testing, it's quite common to encounter situations where your app is dependent on the remote APIs. Network issues, rate limits, or even downtime of the API provider can halt your progress. This can significantly hinder your productivity and make testing more challenging. This is where WireMock comes into play.
|
||||
|
||||
WireMock is an open-source tool that helps developers to create a mock server that simulates the behavior of real APIs, providing a controlled environment for development and testing.
|
||||
|
||||
Imagine you have both an API and a frontend app, and you want to test how the frontend interacts with the API. Using WireMock, you can set up a mock server to simulate the API's responses, allowing you to test the frontend behavior without relying on the actual API. This can be particularly helpful when the API is still under development or when you want to test different scenarios without affecting the actual API. WireMock supports both HTTP and HTTPS protocols and can simulate various response scenarios, including delays, errors, and different HTTP status codes.
|
||||
|
||||
In this guide, you'll learn how to:
|
||||
|
||||
- Use Docker to launch up a WireMock container.
|
||||
- Use mock data in the local development without relying on an external API
|
||||
- Use a Live API in production to fetch real-time weather data from AccuWeather.
|
||||
|
||||
## Using WireMock with Docker
|
||||
|
||||
The official [Docker image for WireMock](https://hub.docker.com/r/wiremock/wiremock) provides a convenient way to deploy and manage WireMock instances. WireMock is available for various CPU architectures, including amd64, armv7, and armv8, ensuring compatibility with different devices and platforms. You can learn more about WireMock standalone on the [WireMock docs site](https://wiremock.org/docs/standalone/docker/).
|
||||
|
||||
### Prerequisites
|
||||
|
||||
The following prerequisites are required to follow along with this how-to guide:
|
||||
|
||||
- [Docker Desktop](https://www.docker.com/products/docker-desktop/)
|
||||
|
||||
### Launching WireMock
|
||||
|
||||
Launch a quick demo of WireMock by using the following steps:
|
||||
|
||||
1. Clone the [GitHub repository](https://github.com/dockersamples/wiremock-node-docker) locally.
|
||||
|
||||
```console
|
||||
$ git clone https://github.com/dockersamples/wiremock-node-docker
|
||||
```
|
||||
|
||||
2. Navigate to the `wiremock-endpoint` directory
|
||||
|
||||
```console
|
||||
$ cd wiremock-node-docker/
|
||||
```
|
||||
|
||||
WireMock acts as the mock API that your backend will communicate with to retrieve data. The mock API responses have already been created for you in the mappings directory.
|
||||
|
||||
3. Start the Compose stack by running the following command at the root of the cloned project directory
|
||||
|
||||
```console
|
||||
$ docker compose up -d
|
||||
```
|
||||
|
||||
After a moment, the application will be up and running.
|
||||
|
||||

|
||||
|
||||
|
||||
You can check the logs by selecting the `wiremock-node-docker` container:
|
||||
|
||||

|
||||
|
||||
4. Test the Mock API.
|
||||
|
||||
```console
|
||||
$ curl http://localhost:8080/api/v1/getWeather\?city\=Bengaluru
|
||||
```
|
||||
|
||||
It will return the following canned response with mock data:
|
||||
|
||||
```plaintext
|
||||
{"city":"Bengaluru","temperature":27.1,"conditions":"Mostly cloudy","forecasts":[{"date":"2024-09-02T07:00:00+05:30","temperature":83,"conditions":"Partly sunny w/ t-storms"},{"date":"2024-09-03T07:00:00+05:30","temperature":83,"conditions":"Thunderstorms"},{"date":"2024-09-04T07:00:00+05:30","temperature":83,"conditions":"Intermittent clouds"},{"date":"2024-09-05T07:00:00+05:30","temperature":82,"conditions":"Dreary"},{"date":"2024-09-06T07:00:00+05:30","temperature":82,"conditions":"Dreary"}]}
|
||||
```
|
||||
|
||||
With WireMock, you define canned responses using mapping files.
|
||||
For this request, the mock data is defined in the JSON file at
|
||||
`wiremock-endpoint/mappings/getWeather/getWeatherBengaluru.json`.
|
||||
|
||||
For more information about stubbing canned responses, refer to the
|
||||
[WireMock documentation](https://wiremock.org/docs/stubbing/).
|
||||
|
||||
|
||||
## Using WireMock in development
|
||||
|
||||
Now that you have tried WireMock, let’s use it in development and testing. In this example, you will use a sample application that has a Node.js backend. This app stack has the following configuration:
|
||||
|
||||
- Local Development Environment: The context in which the Node.js backend and WireMock are running.
|
||||
- Node.js Backend: Represents the backend application that handles HTTP requests.
|
||||
- External AccuWeather API: The real API from which live weather data is fetched.
|
||||
- WireMock: The mock server that simulates the API responses during testing. It runs as a Docker container.
|
||||
|
||||

|
||||
|
||||
- In development, the Node.js backend sends a request to WireMock instead of the actual AccuWeather API.
|
||||
- In production, it connects directly to the live AccuWeather API for real data.
|
||||
|
||||
## Use mock data in local development
|
||||
|
||||
Let’s set up a Node app to send requests to the WireMock container instead of the actual AccuWeather API.
|
||||
|
||||
### Prerequisite
|
||||
|
||||
- Install [Node.js and npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm)
|
||||
- Ensure that WireMock container is up and running (see [Launching Wiremock](#launching-wiremock)
|
||||
|
||||
|
||||
Follow the steps to setup a non-containerized Node application:
|
||||
|
||||
1. Navigate to the `accuweather-api` directory
|
||||
|
||||
Make sure you're in the directory where your `package.json` file is located.
|
||||
|
||||
2. Set the environment variable.
|
||||
|
||||
Open `.env` file placed under `accuweather-api/` directory. Remove the old entries and ensure that it just contains the following single line.
|
||||
|
||||
```plaintext
|
||||
API_ENDPOINT_BASE=http://localhost:8080
|
||||
```
|
||||
|
||||
This will tell your Node.js application to use the WireMock server for API calls.
|
||||
|
||||
3. Examine the Application Entry Point
|
||||
|
||||
- The main file for the application is `index.js`, located in the `accuweather-api/src/api` directory.
|
||||
- This file starts the `getWeather.js` module, which is essential for your Node.js application. It uses the `dotenv` package to load environment variables from the`.env` file.
|
||||
- Based on the value of `API_ENDPOINT_BASE`, the application routes requests either to the WireMock server (`http://localhost:8080`) or the AccuWeather API. In this setup, it uses the WireMock server.
|
||||
- The code ensures that the `ACCUWEATHER_API_KEY` is required only if the application is not using WireMock, enhancing efficiency and avoiding errors.
|
||||
|
||||
|
||||
```javascript
|
||||
require("dotenv").config();
|
||||
|
||||
const express = require("express");
|
||||
const axios = require("axios");
|
||||
|
||||
const router = express.Router();
|
||||
const API_ENDPOINT_BASE = process.env.API_ENDPOINT_BASE;
|
||||
const API_KEY = process.env.ACCUWEATHER_API_KEY;
|
||||
|
||||
console.log('API_ENDPOINT_BASE:', API_ENDPOINT_BASE); // Log after it's defined
|
||||
console.log('ACCUWEATHER_API_KEY is set:', !!API_KEY); // Log boolean instead of actual key
|
||||
|
||||
if (!API_ENDPOINT_BASE) {
|
||||
throw new Error("API_ENDPOINT_BASE is not defined in environment variables");
|
||||
}
|
||||
|
||||
// Only check for API key if not using WireMock
|
||||
if (API_ENDPOINT_BASE !== 'http://localhost:8080' && !API_KEY) {
|
||||
throw new Error("ACCUWEATHER_API_KEY is not defined in environment variables");
|
||||
}
|
||||
// Function to fetch the location key for the city
|
||||
async function fetchLocationKey(townName) {
|
||||
const { data: locationData } = await
|
||||
axios.get(`${API_ENDPOINT_BASE}/locations/v1/cities/search`, {
|
||||
params: { q: townName, details: false, apikey: API_KEY },
|
||||
});
|
||||
return locationData[0]?.Key;
|
||||
}
|
||||
```
|
||||
|
||||
4. Start the Node server
|
||||
|
||||
Before you start the Node server, ensure that you have already installed the node packages listed in the package.json file by running `npm install`.
|
||||
|
||||
```console
|
||||
npm install
|
||||
npm run start
|
||||
```
|
||||
|
||||
You should see the following output:
|
||||
|
||||
```plaintext
|
||||
> express-api-starter@1.2.0 start
|
||||
> node src/index.js
|
||||
|
||||
API_ENDPOINT_BASE: http://localhost:8080
|
||||
..
|
||||
Listening: http://localhost:5001
|
||||
```
|
||||
|
||||
The output indicates that your Node application has successfully started.
|
||||
Keep this terminal window open.
|
||||
|
||||
5. Test the Mocked API
|
||||
|
||||
Open a new terminal window and run the following command to test the mocked API:
|
||||
|
||||
```console
|
||||
$ curl "http://localhost:5001/api/v1/getWeather?city=Bengaluru"
|
||||
```
|
||||
|
||||
You should see the following output:
|
||||
|
||||
```plaintext
|
||||
{"city":"Bengaluru","temperature":27.1,"conditions":"Mostly cloudy","forecasts":[{"date":"2024-09-02T07:00:00+05:30","temperature":83,"conditions":"Partly sunny w/ t-storms"},{"date":"2024-09-03T07:00:00+05:30","temperature":83,"conditions":"Thunderstorms"},{"date":"2024-09-04T07:00:00+05:30","temperature":83,"conditions":"Intermittent clouds"},{"date":"2024-09-05T07:00:00+05:30","temperature":82,"conditions":"Dreary"},{"date":"2024-09-06T07:00:00+05:30","temperature":82,"conditions":"Dreary"}]}%
|
||||
```
|
||||
|
||||
This indicates that your Node.js application is now successfully routing requests to the WireMock container and receiving the mocked responses
|
||||
|
||||
You might have noticed that you’re trying to use `http://localhost:5001` as the URL instead of port `8080`. This is because your Node.js application is running on port `5001`, and it's routing requests to the WireMock container that's listening on port `8080`.
|
||||
|
||||
> [!TIP]
|
||||
> Before you proceed to the next step, ensure that you stop the node application service.
|
||||
|
||||
## Use a Live API in production to fetch real-time weather data from AccuWeather
|
||||
|
||||
To enhance your Node.js application with real-time weather data, you can seamlessly integrate the AccuWeather API. This section of the guide will walk you through the steps involved in setting up a non-containerized Node.js application and fetching weather information directly from the AccuWeather API.
|
||||
|
||||
1. Create an AccuWeather API Key
|
||||
|
||||
Sign up for a free AccuWeather developer account at[https://developer.accuweather.com/](https://developer.accuweather.com/). Within your account, create a new app by selecting `MY APPS` on the top navigation menu to get your unique API key.
|
||||
|
||||

|
||||
|
||||
[AccuWeather API](https://developer.accuweather.com/) is a web API that provides real-time weather data and forecasts. Developers can use this API to integrate weather information into their applications, websites, or other projects.
|
||||
|
||||
2. Change directory to `accuweather-api`
|
||||
|
||||
```console
|
||||
$ cd accuweather-api
|
||||
```
|
||||
|
||||
3. Set your AccuWeather API key using the `.env` file:
|
||||
|
||||
> [!TIP]
|
||||
> To prevent conflicts, ensure that any existing environment variables named `API_ENDPOINT_BASE` or `ACCUWEATHER_API_KEY` are removed before modifying the `.env` file.
|
||||
|
||||
Run the following command on your terminal:
|
||||
|
||||
```console
|
||||
unset API_ENDPOINT_BASE
|
||||
unset ACCUWEATHER_API_KEY
|
||||
```
|
||||
|
||||
It’s time to set the environment variables in the `.env` file:
|
||||
|
||||
```plaintext
|
||||
ACCUWEATHER_API_KEY=XXXXXX
|
||||
API_ENDPOINT_BASE=http://dataservice.accuweather.com
|
||||
```
|
||||
|
||||
Make sure to populate `ACCUWEATHER_API_KEY` with the correct value.
|
||||
|
||||
4. Install the dependencies
|
||||
|
||||
Run the following command to install the required packages:
|
||||
|
||||
```console
|
||||
$ npm install
|
||||
```
|
||||
|
||||
This will install all the packages listed in your `package.json` file. These packages are essential for the project to function correctly.
|
||||
|
||||
If you encounter any warnings related to deprecated packages, you can ignore them for now for this demonstration.
|
||||
|
||||
5. Assuming that you don’t have a pre-existing Node server running on your system, go ahead and start the Node server by running the following command:
|
||||
|
||||
```console
|
||||
$ npm run start
|
||||
```
|
||||
|
||||
You should see the following output:
|
||||
|
||||
```plaintext
|
||||
> express-api-starter@1.2.0 start
|
||||
> node src/index.js
|
||||
|
||||
API_ENDPOINT_BASE: http://dataservice.accuweather.com
|
||||
ACCUWEATHER_API_KEY is set: true
|
||||
Listening: http://localhost:5001
|
||||
```
|
||||
|
||||
Keep this terminal window open.
|
||||
|
||||
6. Run the curl command to send a GET request to the server URL.
|
||||
|
||||
In the new terminal window, enter the following command:
|
||||
|
||||
```console
|
||||
$ curl "http://localhost:5000/api/v1/getWeather?city=Bengaluru"
|
||||
```
|
||||
|
||||
By running the command, you're essentially telling your local server to provide you with weather data for a city named `Bengaluru`. The request is specifically targeting the `/api/v1/getWeather` endpoint, and you're providing the query parameter `city=Bengaluru`. Once you execute the command, the server processes this request, fetches the data and returns it as a response, which `curl` will display in your terminal.
|
||||
|
||||
When fetching data from the external AccuWeather API, you're interacting with live data that reflects the latest weather conditions.
|
||||
|
||||
|
||||
## Recap
|
||||
|
||||
This guide has walked you through setting up WireMock using Docker. You’ve learned how to create stubs to simulate API endpoints, allowing you to develop and test your application without relying on external services. By using WireMock, you can create reliable and consistent test environments, reproduce edge cases, and speed up your development workflow.
|
||||
|
Loading…
Reference in New Issue