This article demonstrates writing test cases for API endpoints and improving application code for better flexibility and testability.
In this article, we will demonstrate how to write test cases for our API endpoints while making necessary changes to our application code. These improvements improve flexibility, testability, and ensure that our endpoints return the correct HTTP status codes.
Before testing, we need to modify the application initialization method to dynamically accept database credentials (DB user, DB password, and DB name) instead of relying on hardcoded constants. This change allows us to specify different credentials during testing.Below is the original initialization method:
The createProduct handler originally returns an HTTP status code of 200 (OK) when a product is successfully created. However, according to RESTful best practices, a 201 (Created) response is more appropriate for resource creation. Below is the existing implementation:
Copy
Ask AI
func (app *App) createProduct(w http.ResponseWriter, r *http.Request) { var p product err := json.NewDecoder(r.Body).Decode(&p) if err != nil { sendError(w, http.StatusBadRequest, "Invalid request payload") return } err = p.createProduct(app.DB) if err != nil { sendError(w, http.StatusInternalServerError, err.Error()) return } sendResponse(w, http.StatusOK, p)}func (app *App) updateProduct(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) _, err := strconv.Atoi(vars["id"]) if err != nil { // handle error appropriately }}
Update the createProduct handler to return a 201 (Created) status code:
Copy
Ask AI
func (app *App) createProduct(w http.ResponseWriter, r *http.Request) { var p product err := json.NewDecoder(r.Body).Decode(&p) if err != nil { sendError(w, http.StatusBadRequest, "Invalid request payload") return } err = p.createProduct(app.DB) if err != nil { sendError(w, http.StatusInternalServerError, err.Error()) return } sendResponse(w, http.StatusCreated, p)}
To test the API, create a separate test file (e.g., app_test.go). In this file, declare your application variable and use the test main function to initialize the application for testing. The test main function, introduced in Go 1.4, is executed to set up and run all tests within the package. Note that the test main function should appear only once per package.Below is an example of initializing your app variable in the test main function:
Copy
Ask AI
package mainimport ( "log" "testing")var a Appfunc TestMain(m *testing.M) { err := a.Initialise(DbUser, DbPassword, "test") if err != nil { log.Fatal("Error occurred while initialising the database") } // Additional setup (e.g., creating a test table) can be done here m.Run()}
In this testing setup, notice how we use the same constants for DB user and DB password but specify a different database name (“test”) to prevent interference with production data. For improved code organization, consider isolating test table creation into a dedicated function.
Using a dedicated test database ensures that your testing operations do not affect live production data. Always isolate your testing environment from production.
How to modify the application initialization to dynamically accept database credentials.
Updating the createProduct handler to return an HTTP 201 status code for resource creation.
Setting up a dedicated test environment to safely run API tests.
By following this improved structure and flow, you ensure that your API is more flexible, testable, and follows best practices for HTTP response codes.For additional details, you can refer to these useful resources: