REST and Test - From Endpoints to Confidence
This week was where things started to get more serious.
Up until now, I had built endpoints that worked, but I had no real guarantee that they would continue working as the system evolved.
This week introduced:
- automated testing
- authentication
- and a much deeper understanding of how a backend should behave
From “it works” to “it is reliable”
Before this week, my workflow was very simple:
- run the app
- test endpoints manually (often with Postman)
- fix bugs if something broke
That approach works early on, but it doesn’t scale.
This week introduced the idea that:
If you don’t test your backend automatically, you don’t actually know if it works.
Testing REST endpoints with Rest Assured
To test the API, I used Rest Assured, which allows HTTP requests to be written directly in Java tests.
Example:
given()
.contentType("application/json")
.when()
.get("/api/v1/companies")
.then()
.statusCode(200);
This made it possible to:
- test endpoints automatically
- verify status codes
- validate JSON responses
It also made the tests feel much closer to how a real client interacts with the API.
Setting up a test environment
One of the biggest challenges was setting up a proper test environment.
The application needed:
- a database connection
- configuration values
- a running application context
This led to several issues, especially when running tests in GitHub Actions.
At one point, my tests failed with:
NullPointerException: inStream parameter is null
This turned out to be caused by missing configuration (config.properties / environment variables).
This was a key lesson:
Tests should not depend on local configuration files.
Instead, I moved towards using environment variables and test-specific configurations.
Authentication with JWT
This week also introduced authentication using JWT (JSON Web Tokens).
The flow works as follows:
- A user logs in with email and password
- The backend validates credentials
- A JWT token is generated
- The client includes the token in future requests
This was implemented in a dedicated service.
Example responsibilities:
- generating tokens
- validating tokens
- extracting user information
Password hashing
Another critical part of authentication was password security.
Instead of storing plain text passwords, I implemented hashing using a password service.
This ensures that:
- passwords are never stored in plain text
- even if the database is compromised, passwords are not directly exposed
This was one of the most important security improvements in the system.
Protecting endpoints
With JWT in place, I started protecting endpoints.
This meant:
- checking for a valid token
- rejecting unauthorized requests
It introduced a new layer of thinking:
Not all endpoints should be accessible to everyone.
For example:
- public endpoints (login)
- protected endpoints (user management)
- role-based access (admin vs user)
Testing authenticated endpoints
Testing became more complex once authentication was introduced.
Now tests had to:
- log in
- extract the token
- include the token in requests
Example flow:
String token =
given()
.contentType("application/json")
.body(loginRequest)
.when()
.post("/api/v1/login")
.then()
.extract()
.path("token");
given()
.header("Authorization", "Bearer " + token)
.when()
.get("/api/v1/companies")
.then()
.statusCode(200);
This made the tests much closer to real-world usage.
Real-world debugging (and frustration)
This week definitely came with its fair share of frustration.
Some of the issues I ran into:
- tests failing in CI but working locally
- missing environment variables
- incorrect JWT setup
- password mismatches
- configuration not loading inside Docker
One specific issue that took time to debug was that:
- the application worked locally
- but failed in GitHub Actions due to missing config values
This forced me to rethink how configuration is handled.
Connecting testing with CI/CD
This was also the point where testing became part of the deployment pipeline.
In GitHub Actions:
- tests run automatically on push
- the build fails if tests fail
This ensures that:
broken code never gets deployed
That was a huge step towards making the project production-ready.
Key takeaways
This week taught me that:
- testing is not optional in real systems
- REST APIs should be validated automatically
- authentication adds complexity, but also structure
- environment configuration must be handled carefully
- CI/CD pipelines rely heavily on reliable tests
This was the week where the backend stopped being something I manually tested and became something I could actually trust.