Layer 4 Session 27 Mock Data

Why Mock Data Matters

Layer 4 begins. Real teams build and test an application's logic long before a real data source is ready. We formalize working against fake data on purpose.

"name": "Kenya" countries.json

Fake data, shaped exactly like the real thing will be.

Estimated time: 35โ€“40 minutes  ยท  Pre-quiz โ†’ Concept โ†’ Lab โ†’ Commit โ†’ Post-quiz

1. Learning Objective

By the end of this session you will be able to:

  • Explain why building against mock data before a real API exists speeds up development
  • Write a mock data file that mirrors the shape a future real data source will have
  • Explain what a "contract" means in the context of data shape
  • Recognise this as a largely concept session, similar to Sessions 08 and 16
  • Identify the risk of a mock data shape silently diverging from the real data shape it is meant to mirror

2. Pre-Coding Quiz

Answer these before reading the concept explanation or writing any code. It is fine to get these wrong โ€” that is the point. You need 4/5 to proceed to the lab.

Question 1 of 5

Why would a team build the Country Explorer's search feature against a hand-written mock_countries.py file instead of waiting for a real API to be ready?

Depending on an external, possibly-unfinished, possibly-unreliable data source blocks all progress on everything else. Mock data lets the rest of the application be built, used, and tested completely independently.
Question 2 of 5

What does it mean for mock data to "mirror the shape" of a future real data source?

If real data will have name, region, and population keys with string/string/int types, the mock data should use exactly the same keys and types โ€” even though "Kenya" and 54000000 are made-up placeholder values, not scraped from a real source.
Question 3 of 5

What is a "contract" in the sense used by this session?

A data contract is the agreed structure โ€” which keys exist, what types they hold โ€” that all code can rely on. As long as real data honors the same contract as the mock data, code built against the mock keeps working without changes.
Question 4 of 5

What risk exists if the mock data's shape silently diverges from what the real data source will actually provide (e.g. mock uses "pop", but the real API returns "population")?

Mock data is only useful if it honestly represents the shape real data will have. If they diverge, all the work done "safely" against the mock turns out to be built on a false assumption, and breaks the moment real data is introduced.
Question 5 of 5

Why is this session mostly concept, with a comparatively small lab?

This follows the same pattern established twice before in the curriculum: build the mental model first (why does this practice exist, what problem does it solve), then build the concrete implementation in the following session.

3. The Concept โ€” Why Mock Data Matters

MOCK DATAsame shapeCONTRACTname, region,populationREAL API (LATER)same shape

Application code depends on the SHAPE (the contract), not on whether the data source is mock or real.

Building against fake data on purpose

Every session so far has technically used mock data โ€” hand-typed Country instances. This session makes that a deliberate practice: build and test your application's real logic against a fake data source that mirrors what a real one will eventually look like.

# mock_countries.py โ€” deliberately fake, but shaped like the real thing will be
MOCK_COUNTRIES = [
    {"name": "Kenya", "region": "Africa", "population": 54000000},
    {"name": "Ghana", "region": "Africa", "population": 31000000},
    {"name": "Peru", "region": "Americas", "population": 33000000},
    {"name": "Japan", "region": "Asia", "population": 125000000},
    {"name": "Norway", "region": "Europe", "population": 5400000},
]

A contract is a shape everyone agrees to honor

The "contract" is simply: every country record has a name (str), a region (str), and a population (int). As long as both the mock data and a future real API honor this same contract, code written against one will keep working against the other.

The independence this buys us

With a mock data source in place, every remaining feature โ€” search, filtering, the whole CountryExplorer built in Layer 2 and 3 โ€” can be developed and fully exercised without a real API existing yet, or even being reachable over the network at all.

from mock_countries import MOCK_COUNTRIES

countries = [Country.from_dict(r) for r in MOCK_COUNTRIES]
explorer = CountryExplorer(countries=countries)
print(explorer.total_population)   # works completely offline, no network needed

The risk: silent divergence from the real shape

Mock data is only useful if it honestly represents what real data will look like. If the mock and the eventual real source disagree on key names or types, everything built "safely" against the mock will break the moment real data arrives โ€” an important risk to keep in mind as we build Session 30's formal data contracts.

Concept session: Like Sessions 08 and 16, the goal here is understanding the practice before building the concrete implementation in Session 28.

4. Lab

Lab objective: Write a mock country dataset with 10 records mirroring the eventual real API shape, and build the full explorer entirely offline from it.

What you will build

A file called mock_countries.py and a small script that uses it.

Step-by-step instructions

1

Create mock_countries.py with 10 diverse records

Use a variety of regions and population sizes โ€” this will matter for later filtering exercises.

# mock_countries.py
MOCK_COUNTRIES = [
    {"name": "Kenya", "region": "Africa", "population": 54000000},
    {"name": "Ghana", "region": "Africa", "population": 31000000},
    {"name": "Nigeria", "region": "Africa", "population": 223000000},
    {"name": "Peru", "region": "Americas", "population": 33000000},
    {"name": "Canada", "region": "Americas", "population": 38000000},
    {"name": "Brazil", "region": "Americas", "population": 216000000},
    {"name": "Japan", "region": "Asia", "population": 125000000},
    {"name": "India", "region": "Asia", "population": 1428000000},
    {"name": "Norway", "region": "Europe", "population": 5400000},
    {"name": "Germany", "region": "Europe", "population": 84000000},
]
2

Create explore_offline.py that imports the mock and builds Country instances

# explore_offline.py
from mock_countries import MOCK_COUNTRIES

class Country:
    def __init__(self, name, region, population):
        self.name = name
        self.region = region
        self.population = population

    def summary(self):
        return f"{self.name} ({self.region}): pop. {self.population:,}"

    @classmethod
    def from_dict(cls, data):
        return cls(**data)

countries = [Country.from_dict(r) for r in MOCK_COUNTRIES]
print(len(countries))
3

Build a CountryExplorer entirely offline, with total_population and country_count as @property

class CountryExplorer:
    def __init__(self, countries):
        self.countries = countries

    @property
    def country_count(self):
        return len(self.countries)

    @property
    def total_population(self):
        return sum(c.population for c in self.countries)

explorer = CountryExplorer(countries=countries)
print(explorer.country_count)
print(explorer.total_population)
4

Print every summary, proving the whole application works with zero network access

for c in explorer.countries:
    print(c.summary())
5

Write a comment describing the contract: what keys and types every record must have

This will become Session 30's formal data contract โ€” write it in plain English for now.


5. Expected Files Changed

FileActionWhy
mock_countries.py Created A mock dataset of 10 countries mirroring the eventual real API shape.
explore_offline.py Created Builds the full explorer entirely from mock data, no network needed.
docs/sessions/session-27/index.html Created This session document.
If you find yourself editing any other file, stop. This session touches exactly 3 files.

6. Commit Checkpoint

Once the lab is complete and you can explain every line, make this exact commit:

git add mock_countries.py explore_offline.py docs/sessions/session-27/index.html
git commit -m "session-27: build a mock dataset and run the explorer entirely offline"
Do not commit until you can answer out loud: "What is the "contract" mock_countries.py is honoring, and why does that matter for a future real data source?"

7. Code Review Checklist

Go through your code line by line and check each item:


8. Post-Coding Quiz

Same 5 questions. Take it again now that you have written and run the code. You need 4/5 to mark this session complete.

Question 1 of 5

Why would a team build the Country Explorer's search feature against a hand-written mock_countries.py file instead of waiting for a real API to be ready?

Depending on an external, possibly-unfinished, possibly-unreliable data source blocks all progress on everything else. Mock data lets the rest of the application be built, used, and tested completely independently.
Question 2 of 5

What does it mean for mock data to "mirror the shape" of a future real data source?

If real data will have name, region, and population keys with string/string/int types, the mock data should use exactly the same keys and types โ€” even though "Kenya" and 54000000 are made-up placeholder values, not scraped from a real source.
Question 3 of 5

What is a "contract" in the sense used by this session?

A data contract is the agreed structure โ€” which keys exist, what types they hold โ€” that all code can rely on. As long as real data honors the same contract as the mock data, code built against the mock keeps working without changes.
Question 4 of 5

What risk exists if the mock data's shape silently diverges from what the real data source will actually provide (e.g. mock uses "pop", but the real API returns "population")?

Mock data is only useful if it honestly represents the shape real data will have. If they diverge, all the work done "safely" against the mock turns out to be built on a false assumption, and breaks the moment real data is introduced.
Question 5 of 5

Why is this session mostly concept, with a comparatively small lab?

This follows the same pattern established twice before in the curriculum: build the mental model first (why does this practice exist, what problem does it solve), then build the concrete implementation in the following session.

9. Reflection Questions

Think through these after the post-quiz. No right answer โ€” they are for discussion.

  1. What would break in explore_offline.py if one mock record used "pop" instead of "population" as a key? Where exactly would the failure occur?
  2. Why is it valuable that explore_offline.py runs with literally zero network access?
  3. Can you think of a real project (not this one) where you have seen or could imagine mock data being useful before a backend was ready?
  4. What is the cost of maintaining mock data as the "real" contract evolves over time? How would you keep them in sync?

10. What Breaks If This Knowledge Is Missing?

  • Blocked development: Without mock data, building and testing the Country Explorer's logic would be blocked on a real, possibly unfinished or unreliable API being available โ€” an unnecessary dependency for logic that has nothing to do with networking.
  • The data access layer (Session 28): The next session wraps this mock data behind a proper repository interface โ€” the mock dataset from this session becomes the first "backend" that repository talks to.
  • Data contracts (Session 30): The plain-English contract description written in this lab becomes the formal, enforced contract in Session 30, using type hints and dataclasses.

11. What We Learned

Python concept mastered: Deliberately building and testing against mock data that mirrors a real data source's shape, and the concept of a data contract.

Unlocks: The entire application can now be developed and demonstrated completely independent of any real, external data source.

Next session: Session 28 โ€” Building a Data Access Layer. We wrap this mock data behind a proper data-access layer, separating "how data is fetched" from "what the application does with it."