DEV Community

John Builds
John Builds

Posted on

Our test stubbed the bug, so the bug passed

A vendor API we integrate with sends a field called publicaly_available_post_id.

That is not a typo I introduced writing this post. That is the field name. It ships in their docs and it ships on the wire, missing the "l", and it has presumably been that way since whoever wrote the endpoint typed it.

Our code read publicly_available_post_id. Correct English. A field the vendor has never once sent.

That should have been caught immediately, and here is why it wasn't: the test stubbed the correctly-spelled field too.

I had written something like this:

stub_response(
  status: "PUBLISH_COMPLETE",
  publicly_available_post_id: "7391..."
)
Enter fullscreen mode Exit fullscreen mode

and then asserted that our reader picked up the ID. It did. Green. The test passed for months.

What that test proved is that our reader agrees with our stub. Both were written by the same person on the same afternoon out of the same wrong assumption, so of course they agreed. The vendor was never in the room.

The failure surfaced somewhere else entirely. There was a fallback: if the post ID is missing, store the temporary upload handle instead. So the first post that ever completed publishing stored an upload handle where a permanent post ID belongs. Nothing errored. The record looked fine. The breakage appeared weeks later in a different subsystem, where the metrics fetcher asked for stats on an ID the vendor had no idea about and got back an error message about integers.

Three things I took from it.

Copy field names, never retype them. Every character of a vendor's wire format should arrive in your codebase via paste, from their reference response. The moment you type it from memory you have a second source of truth, and your test will loyally defend it.

A stub you wrote is not evidence about the vendor. It is evidence about you. If a test's fixture and the code under test share an author and an assumption, the test can only catch typos in the implementation, not errors in the belief. Somewhere in the suite there should be one real captured response from the actual API, warts and misspellings preserved.

Watch fallbacks that make an absent value look present. The || upload_handle fallback turned "we have no ID" into "here is an ID", which is how a parsing bug got laundered into a data integrity bug and shipped off for another team's code to discover.

The fix was three lines. Read the misspelled field first, keep the correct spelling as a fallback in case they ever fix it, and re-stub the test from a raw response captured off the wire.

Top comments (0)