I’m building RunHop in public — a social + event platform for running races, built on NestJS.
Today wasn’t a feature day. It was a correctness day. I found a test that passed while testing the wrong behavior, and fixed a quiet 500 hiding behind a non-null assertion. Both are easy to miss, and both are exactly how bugs slip into production.
The Bug: An E2E Test That Didn’t Test Updates
In the Race module, I enforce a rule: once an event is published, races under it can’t be created, updated, or deleted.
I had an e2e test named:
it('should be 400 if updating a race on a published event', async () => { // draftEvent here is now published because of beforeAll const res = await request(app.getHttpServer()) .post(/api/v1/events/${draftEvent.id}/races) .set('Authorization', Bearer ${accessToken}) .send({ name: 'Race Test 2', distance: 123.45, unit: 'test-unit-2', maxParticipants: 500, price: 1000 });
expect(res.statusCode).toBe(400); });
The problem is obvious once you stare at it: this test is calling POST /events/:id/races — which is the create endpoint. It wasn’t testing updates at all. The test passed, but for the wrong reason.
This is the dangerous kind of bug: it gives you confidence you didn’t earn.
The Fix
I changed it to call the correct update endpoint:
it('should be 400 if updating a race on a published event', async () => {
const res = await request(app.getHttpServer())
.patch(`/api/v1/races/${raceTest2.id}`)
.set('Authorization', `Bearer ${accessToken}`)
.send({ name: 'Updated Race Test' });
expect(res.statusCode).toBe(400);
});
That’s it. Same assertion, correct endpoint. Now the test actually verifies the rule I care about.
The Other Bug: Non-Null Assertions Hiding 500s
In RaceService, I had:
async findById(id: string) {
return this.prismaService.race.findUnique({ where: { id } });
}
Every caller did this:
const race = await this.findById(id);
await this.verifyEventIsDraft(race!.eventId);
If a race didn’t exist, findUnique() returned null. The non-null assertion (race!) then caused a runtime error when accessing race!.eventId. That’s a 500, and it’s the worst kind: a missing record should be a 404, not an internal crash.
The Fix
I moved the not-found handling into findById():
async findById(id: string) {
const result = await this.prismaService.race.findUnique({ where: { id } });
if (!result) throw new NotFoundException('Race not found');
return result;
}
Now every caller gets a consistent 404 for missing races, and I can remove defensive checks everywhere else.
Why This Matters
These changes are small, but they keep the system honest:
The e2e tests now prove what they say they prove.
The service layer returns correct HTTP errors instead of crashing.
It’s easy to chase new features and ignore this kind of cleanup. But if you’re building in public (or building at all), correctness work is what keeps the platform stable as it grows.
Takeaway
Passing tests don’t mean correct behavior. Look at the HTTP calls. Make sure the tests are hitting the right routes. And when you see ! on a nullable value, treat it as a warning — it’s often hiding a missing NotFoundException.
Top comments (0)