Testing and debugging API code is the safety net that catches mistakes before your software breaks for real users. For the 200-901 exam, you need to know how to write small, automated checks (unit tests), how to fake parts of your system (mocking), and how to find hidden bugs (debugging). These skills separate a developer who ships broken code from one who delivers reliable APIs.
Jump to a section
A simple way to picture Testing and Debugging API Code
You are opening a 24-hour bakery that serves 500 customers a day. Before you let anyone in, you test every oven at 350 degrees for 30 minutes to make sure it heats evenly — that is unit testing, checking each small part works alone. Then you write a fake customer order for a dozen croissants and pretend the till shows £24.00; this is mocking, because you are using a pretend version of the payment system so you do not have to charge a real credit card. Finally, when the first real batch of sourdough comes out burnt on the bottom, you watch the temperature gauge, check the timer, and realise the cooling fan kicked on too early — that is debugging, tracing the problem step by step.
In the bakery, if you never tested the ovens individually, you might blame the flour for a bad loaf when the real fault was the thermostat. In API code, if you never mock the payment service, your tests might accidentally charge a real user £1,000 during a dry run. The specific mapping: unit testing is checking each oven (each function) in isolation, mocking is using a pretend credit-card machine (a fake service), and debugging is reading the burnt-loaf clues (error logs and breakpoints) to fix the fan timer. This analogy only works for testing and debugging code because it depends on isolating components, faking dependencies, and tracing failure paths — not reusable for load balancing or cloud migration.
Software is built from thousands of tiny pieces of code called functions. A function is a block of instructions that does one thing, like 'add two numbers' or 'look up a user's email address'. When you write a new function, you want to prove it works correctly before you connect it to the rest of your program. That proof is a unit test — a small, automated script that feeds the function a known input and checks that the output is exactly what you expect.
Unit tests run in isolation, meaning they do not touch a real database, a real payment gateway, or a real network. If a unit test tries to call an external service that costs money or takes minutes to respond, it becomes slow, fragile, and expensive. To avoid this, developers use mocking — they replace the real service with a fake version that returns a predetermined answer instantly. For example, if your code calls a weather API that charges per request, you create a mock that always returns 'sunny, 22°C' so your test runs free and fast.
The tools that run unit tests are called test runners. Popular ones in the Cisco DevNet world include PyTest for Python, Mocha for JavaScript, and JUnit for Java. A test runner scans your project for files that contain test functions, runs each one, and reports which passed or failed.
Debugging is the process of finding and fixing a bug — a mistake in your code that causes unexpected behaviour. When a unit test fails, you have a clue: you know exactly which function broke and what input caused it. But debugging is broader: it happens when a real user reports a crash, a log shows an error, or an API returns the wrong status code. Developers use a debugger, a special tool that lets you pause your program mid-execution, inspect the values of variables (named storage boxes for data), and step through code line by line.
Why does this matter for APIs? An API is a set of rules that lets one piece of software talk to another. If your API has a bug — say it returns '200 OK' when it should return '404 Not Found' — every program that calls it will act wrongly. Unit testing catches these bugs before you deploy (release to production). Mocking ensures your tests stay fast and independent. Debugging helps you fix bugs that slip through.
Common terms you will see on the exam:
Assertion: a statement in a test that says 'I expect this value to equal that'. If the assertion is false, the test fails.
Test coverage: a percentage that shows how much of your code is exercised by tests. High coverage does not guarantee perfect code, but low coverage means many untested functions.
Side effect: an action your code takes that changes something outside itself, like writing to a file or sending an email. Unit tests try to avoid side effects because they make tests unpredictable.
The exam expects you to recognise that unit testing, mocking, and debugging are three distinct but related activities. You will see scenario questions where you must choose the right technique for the problem. For instance, if a test fails because it depends on a database that is offline, the fix is to mock the database, not to rewrite the test.
Write a Unit Test
Create a new test file (e.g., test_fare.py) and import the function you want to test (e.g., calculate_fare). Write a function that calls calculate_fare with specific inputs and uses an assert statement to check the output. This step matters because it defines the expected behaviour before you even run the code.
Run the Test
Execute the test runner (e.g., 'pytest test_fare.py'). The runner discovers all test functions and runs them. If the test passes, you have confirmation that the function works for that input. If it fails, you know immediately that something is wrong.
Mock the External Dependency
Identify the part of your code that calls an external API (like a maps service). Use a mocking library (e.g., unittest.mock in Python) to replace that API call with a function that returns a hardcoded value. This ensures your test never actually calls the external service, making it fast and reliable.
Debug a Failed Test
When a test fails, open the code in a debugger (e.g., Visual Studio Code or PyCharm). Set a breakpoint on the line where the test fails. Run the test again in debug mode. The program stops at the breakpoint — inspect variables like input and output to see where the logic goes wrong. This step reveals the exact cause.
Fix the Bug and Re-run Tests
Edit the production code to correct the bug (e.g., add a check for zero distance). Save the file and re-run the test suite. All tests should now pass. This step confirms that the fix works and does not break anything else.
Imagine you work for a ride-sharing company called GoRide. You are building a new API endpoint that calculates fare estimates: the user sends a pickup and drop-off location, and the API returns the price. Your boss wants it live on Monday. Here is what an IT professional actually does with testing, mocking, and debugging.
First, you write a unit test for the core function that computes fare. That function takes two inputs: distance in kilometres and a time multiplier for surge pricing. You test it with a distance of 5 km and a multiplier of 1.0; you assert the result is exactly £7.50 based on your formula. You run the test and it passes — the function is correct.
Next, you write a unit test for the function that looks up the distance between two addresses. This function calls a third-party mapping API (Google Maps or similar). You do not want your test to actually hit Google Maps every time — that would be slow, cost money, and fail if your internet is down. So you mock the mapping API. Your mock returns a fixed distance of 5 km whenever it is called with any coordinates. Now your test can run offline in milliseconds and verify that the fare is calculated correctly using the mocked distance.
On Friday, you integrate everything and run all tests. One test fails: the endpoint returns a fare of £0.00 when the pickup and drop-off are the same address. You debug by adding a breakpoint — a pause command — inside the fare function. You run the test again inside your debugger (for example, Visual Studio Code's debugger). The program halts at the breakpoint, and you inspect the variable 'distance'. It is 0.0. The fare formula multiplies distance by the rate, so 0 * rate = £0.00. Now the bug is obvious: the code did not check for same-address input. You add a check that returns an error message instead of £0.00.
You also use test coverage tools to see which parts of your code have no tests. You discover a helper function that converts currency to cents was never tested. You write a unit test for it.
Finally, you set up continuous integration (CI) — an automated system that runs all your unit tests every time you push code to the shared repository. If a teammate accidentally breaks the fare calculation, the CI system alerts everyone immediately.
In summary, a real developer's day involves:
Writing unit tests for every new function.
Mocking external APIs (like payment gateways, mapping services, and databases).
Running tests locally dozens of times.
Using a debugger to find the root cause of failures.
Checking test coverage reports to identify untested code.
The 200-901 exam tests your understanding of three specific concepts: unit testing, mocking, and debugging. You will see multiple-choice questions, single-answer questions, and possibly drag-and-drop scenarios. The exam does not ask you to write code — it asks you to identify the correct technique, tool, or behaviour.
Here are the exact topics you must memorise:
Unit testing: know that it tests a single function or method in isolation. The exam loves asking: 'Which type of test verifies that a single function returns the correct output for a given input?' The answer is always unit testing.
Mocking: know that mocking replaces a real dependency (like a database or external API) with a fake object that returns controlled responses. A common trap is that the exam shows a scenario where a test fails because a network call times out; they ask what to do. The correct answer is 'mock the network call' — not 'increase the timeout' or 'disable the test'.
Debugging: know that debugging is the process of identifying and removing errors. The exam may ask which tool you use to pause execution and inspect variables. The correct answer is a debugger (like gdb, pdb, or the browser DevTools debugger). They might also ask: 'What is a breakpoint?' A breakpoint is a deliberate stop point in code.
Trap patterns to watch for:
The exam might describe a scenario where a test passes when run alone but fails when run with all tests. The correct answer is that the test modifies shared state (side effect), violating isolation.
They might ask about 'test-driven development' (TDD): writing the test before the code. This is a methodology, not a tool. Recognise it as a design process.
They might confuse 'unit testing' with 'integration testing'. Integration testing tests multiple components together. Unit testing tests one component in isolation. The exam will present a scenario and ask which type of test is best. If the scenario involves two APIs talking to each other, it is integration testing. If it involves one function, it is unit testing.
Key definitions to memorise:
Assert: a statement that checks if a condition is true.
Test double: a generic term for any fake object used in testing (mocks, stubs, fakes).
Regression: a bug introduced when new code breaks previously working features. Unit tests catch regressions.
Finally, the exam expects you to know that debugging is not just about code: it also involves reading logs, using print statements, and setting breakpoints. The most common debugging tool in API code is the network tab in browser DevTools, where you can see every request, response, and error code.
Unit testing verifies a single function or method works correctly in isolation, without touching databases, networks, or file systems.
Mocking replaces a real external dependency with a fake version so that tests run fast, cheap, and reliably.
A debugger lets you pause code execution at a breakpoint and inspect variable values to find the root cause of a bug.
Test coverage measures what percentage of your code is exercised by tests, but high coverage does not guarantee high quality.
Assertions are the core of any unit test — they check that actual output matches expected output and fail the test if they do not.
Integration testing differs from unit testing because it tests how multiple components work together, while unit testing tests components alone.
These come up on the exam all the time. Here's how to tell them apart.
Unit Test
Tests a single function or method in isolation.
Uses mocks to replace external dependencies.
Fast to run (milliseconds per test).
Integration Test
Tests multiple components working together.
Uses real databases, APIs, or file systems.
Slower to run (seconds or minutes per test).
Mocking
Can verify that a function was called with specific arguments.
Used for behaviour verification.
Tracks how many times a function was called.
Stubbing
Only returns a fixed value; does not track calls.
Used for state verification.
Simulates a response without recording interactions.
Debugging
Pauses execution to inspect variables interactively.
Requires a debugger tool (e.g., pdb, VS Code).
Best for finding the root cause of a tricky bug.
Logging
Records events to a file without pausing.
Requires inserting print or log statements in code.
Best for monitoring production systems over time.
Mistake
Unit testing is only for large software companies, not for small projects.
Correct
Every piece of code benefits from unit tests, whether it is a 100-line script or a million-line system. Unit tests catch mistakes early, regardless of project size.
Beginners often think testing is optional bureaucracy because they have never experienced the pain of a bug in production. They assume small projects are simple enough to test manually.
Mistake
Mocking is the same as stubbing — they are interchangeable terms.
Correct
A mock is a test double that can verify behaviour (e.g., 'was the function called with the right arguments?'). A stub only returns a fixed value. Both are fakes, but they serve different purposes.
Many tutorials use the terms loosely, and beginners absorb them as synonyms. The exam tests the distinction.
Mistake
If all unit tests pass, the code is bug-free.
Correct
Unit tests only prove that the tested functions behave correctly under the tested inputs. They cannot prove the absence of all bugs — especially integration issues, performance issues, or unexpected user behaviour.
This mistake comes from a natural desire for certainty. Beginners want a green checkmark to mean 'perfect', but testing is about reducing risk, not eliminating it.
Mistake
Debugging is just reading the error message and fixing the typo.
Correct
Debugging is a systematic process of forming hypotheses, testing them, and isolating the root cause. Error messages often point to the symptom, not the cause. You must trace the logic.
Beginners have only encountered simple typos that produce clear error messages. They have not experienced subtle bugs like race conditions or off-by-one errors that require stepping through code.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
Unit testing tests one isolated piece of code (like a single function). Integration testing tests how multiple pieces work together, often involving a real database or API.
No, only mock services that are slow, expensive, unreliable, or have side effects (like sending emails or charging credit cards). Simple utilities like string formatters do not need mocking.
A breakpoint is a marker you set in your code that tells the debugger to pause execution at that line so you can inspect the current state of variables and step through subsequent lines.
First, check the server logs to see the actual error message and stack trace. Then reproduce the error locally, set breakpoints in the endpoint handler, and send the same request to step through the code.
It means every line of your code has been executed by at least one test. However, it does not guarantee that every possible input or edge case has been tested.
No. A stub returns a fixed answer. A mock can also verify that a function was called with specific arguments. Both are types of test doubles, but mocks are used for behaviour verification.
You've finished Testing and Debugging API Code. Continue through the 200-901 study guide to build a complete picture of the exam.
Done with this chapter?