Skip to content

terenzio/MariaDBTestContainerGolang

Repository files navigation

MariaDB Test Container with Golang CRUD API

This project demonstrates a simple CRUD (Create, Read, Update, Delete) API built using the Gin framework in Golang. The API interacts with a MariaDB database, and the project includes unit tests that utilize MariaDB test containers for isolated and reproducible testing.

Features

  • CRUD API: Endpoints for managing Classroom and Student entities.
  • MariaDB Integration: Database connection and schema setup.
  • Test Containers: Automated testing with MariaDB test containers for a clean and isolated environment.
  • Best Practices: Code comments and structure following Golang best practices.

Project Structure

  • main.go: Entry point for the API server.
  • handlers.go: Contains the API handlers for CRUD operations.
  • models.go: Defines the Classroom and Student models.
  • db.go: Database connection setup.
  • schema.sql: SQL schema for creating the database tables.
  • main_test.go: Unit tests for the API using MariaDB test containers.

Prerequisites

  • Go (1.20 or later)
  • Docker (for test containers)
  • MariaDB client (optional, for manual database inspection)

Setup and Usage

1. Clone the Repository

git clone https://github.com/terenzio/MariaDBTestContainerGolang.git
cd MariaDBTestContainerGolang

2. Install Dependencies

go mod tidy

3. Run the API Server

Start the API server locally:

go run .

The server will start on http://localhost:8080.

4. API Endpoints

Classroom Endpoints

  • GET /classrooms: Retrieve all classrooms.
  • POST /classrooms: Create a new classroom.
  • GET /classrooms/:id: Retrieve a specific classroom by ID.
  • PUT /classrooms/:id: Update a specific classroom by ID.
  • DELETE /classrooms/:id: Delete a specific classroom by ID.

Student Endpoints

  • GET /students: Retrieve all students.
  • POST /students: Create a new student.
  • GET /students/:id: Retrieve a specific student by ID.
  • PUT /students/:id: Update a specific student by ID.
  • DELETE /students/:id: Delete a specific student by ID.

5. Run Tests

Run the unit tests, which use MariaDB test containers:

go test ./...

6. Database Schema

The database schema is defined in schema.sql. It includes two tables:

  • classroom: Stores classroom information.
  • student: Stores student information, with a foreign key referencing classroom.

7. Test Container Setup

The tests use the testcontainers-go library to spin up a MariaDB container. The container is configured with:

  • MYSQL_ROOT_PASSWORD: Root password for the database.
  • MYSQL_DATABASE: Name of the test database.

The schema is loaded into the container during test setup, ensuring a clean environment for each test run.

Benefits of Using Testcontainers

Testcontainers is a powerful library for managing Docker containers in tests. It provides several benefits, especially for integration testing with databases like MariaDB. Below are some key advantages and examples from this repository:

1. Isolated Testing Environment

Each test run starts with a fresh MariaDB container, ensuring that tests do not interfere with each other. This eliminates the risk of flaky tests caused by leftover data or state from previous runs.

Example: In main_test.go, the setupTestDB function initializes a new MariaDB container for each test:

containerReq := testcontainers.ContainerRequest{
    Image:        "mariadb:latest",
    Env:          map[string]string{"MYSQL_ROOT_PASSWORD": "root", "MYSQL_DATABASE": "testdb"},
    ExposedPorts: []string{"3306/tcp"},
    WaitingFor:   wait.ForListeningPort("3306/tcp"),
}
mariaC, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
    ContainerRequest: containerReq,
    Started:          true,
})

2. Reproducibility

By using Docker containers, the tests run in a consistent environment regardless of the host system. This ensures that the tests behave the same way on any developer's machine or CI/CD pipeline.

Example: The database schema is loaded into the container during test setup, ensuring a clean and consistent database state:

schema, err := os.ReadFile("schema.sql")
statements := strings.Split(string(schema), ";")
for _, stmt := range statements {
    stmt = strings.TrimSpace(stmt)
    if stmt != "" {
        _, execErr := testDB.Exec(stmt)
        if execErr != nil {
            t.Fatalf("Could not exec statement: %v", execErr)
        }
    }
}

3. Ease of Use

Testcontainers abstracts away the complexity of managing Docker containers. With just a few lines of code, you can start a container, configure it, and connect to it.

Example: The testcontainers-go library makes it easy to map ports and retrieve the container's host and port:

host, _ := mariaC.Host(ctx)
port, _ := mariaC.MappedPort(ctx, "3306")
dsn := fmt.Sprintf("root:root@tcp(%s:%s)/testdb?parseTime=true", host, port.Port())
testDB, err = sql.Open("mysql", dsn)

4. Automatic Cleanup

Testcontainers ensures that containers are stopped and removed after the tests are completed, preventing resource leaks.

Example: The setupTestDB function returns a teardown function to clean up resources:

return func() {
    testDB.Close()
    mariaC.Terminate(ctx)
}

5. Integration Testing Made Simple

Testcontainers allows you to test your application with real dependencies (e.g., MariaDB) instead of mocks or in-memory databases. This provides greater confidence in the correctness of your code.

Example: The tests in main_test.go interact with a real MariaDB instance, verifying the CRUD operations:

// Test Create Classroom
w := httptest.NewRecorder()
req := httptest.NewRequest("POST", "/classrooms", strings.NewReader(`{"name":"Math"}`))
req.Header.Set("Content-Type", "application/json")
r.ServeHTTP(w, req)
assert.Equal(t, http.StatusCreated, w.Code)

By leveraging Testcontainers, this project ensures robust and reliable integration tests, making it easier to catch issues early in the development process.

Contributing

Feel free to fork this repository and submit pull requests for improvements or additional features.

License

This project is licensed under the MIT License. See the LICENSE file for details.


Happy coding!

About

MariaDBTestContainerGolang

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages