NetAuto Academy

NAPALM for Network Engineers

Testing NAPALM Without Real Devices

Advanced14 min read

What you'll learn

  • That NAPALM ships a genuine, built-in mock driver -- not something this curriculum built
  • Its real fixture format and file-naming convention
  • Which methods are automatically mocked, and which are not
  • How to script a real, specific failure for testing error-handling code
🎓 Teach This Lesson

Listen to a guided explanation of this lesson.

Spoken narration isn't supported in this browser.

A real library feature, not a simulation this curriculum built

Verify this claim before trusting it -- which is exactly what happened

Every prior "no real device" path in this curriculum (Your First Network Automation onward) was a hand-written simulate_connection()-style stand-in. NAPALM is different: get_network_driver("mock") returns a real class shipped inside the napalm package itself -- discovered directly from get_network_driver()'s own source, not assumed to exist.

get_network_driver's real source, installed napalm 5.2.0 (excerpt)
def get_network_driver(name, prepend=True):
  if name == "mock":
      return MockDriver
  ...

Verified directly by reading the installed package's source. 'mock' is a special-cased, first-class driver name -- not a convention this module invented.

Quick checkConcept check
What is NAPALM's mock driver, based on what was actually verified from source?

The fixture format: real JSON files

MockDriver's fixture-loading, real source, installed napalm 5.2.0 (excerpt)
def mocked_data(path, name, count):
  filename = "{}.{}".format(os.path.join(path, name), count)
  with open(filename) as f:
      result = json.loads(f.read())
  if "exception" in result:
      raise_exception(result)
  return result

Verified directly. A fixture file is named <path>/<method_name>.<call_count> -- e.g. get_facts.1 for the first call to get_facts() -- and holds real JSON.

a real fixture file used earlier in this module -- fixtures/sw1/get_facts.1
{
"os_version": "16.9.5, RELEASE SOFTWARE (fc3)",
"uptime": 1234567.0,
"interface_list": ["GigabitEthernet0/1", "GigabitEthernet0/2"],
"vendor": "Cisco",
"serial_number": "SW1-SN-001",
"model": "Catalyst 3850",
"hostname": "SW1",
"fqdn": "SW1.example.local"
}

This exact file is what produced Lesson 3's real, verified get_facts() output -- the mock driver isn't inventing data, it's reading it back from a file matching FactsDict's real shape.

Quick checkIdentify the correct code
A learner wants get_interfaces() to be the third call served by the mock driver for a device whose fixtures live in fixtures/sw2/. What must the fixture filename be?

Which methods are mocked automatically

real source, installed napalm 5.2.0
def is_mocked_method(method):
  mocked_methods = ["traceroute", "ping"]
  if method.startswith("get_") or method in mocked_methods:
      return True
  return False

Verified directly. Every getter (anything starting with get_) is automatically served from a fixture file -- no manual wiring needed. open(), close(), and rollback() are NOT auto-mocked -- they're implemented directly with real Python logic instead (next).

Quick checkScenario
Why don't open(), close(), and rollback() need a fixture file, unlike get_facts() or get_interfaces()?

Scripting a real, specific failure

a genuine failure, via fail_on_open -- real, verified
driver = driver_cls(
  hostname="SW4",
  username=os.environ.get("NAPALM_USERNAME", ""),
  password=os.environ.get("NAPALM_PASSWORD", ""),
  optional_args={"path": "fixtures/sw1", "fail_on_open": True},
)
try:
  driver.open()
except ConnectionException as e:
  print(repr(e))

fail_on_open is a real, documented optional_arg on MockDriver -- forces open() to raise, for testing an unreachable-device code path without a real unreachable device.

output — real, verified
ConnectionException('You told me to do this')

Real, verified output -- MockDriver's own literal message, not something invented for this lesson.

a scripted exception via fixture -- fixtures/sw5/get_facts.1
{
"exception": "napalm.base.exceptions.ConnectAuthError",
"args": ["SW5 rejected the credentials"]
}

A fixture holding an 'exception' key causes that exact exception to be raised instead of returning data -- confirmed directly from mocked_data()'s source above.

output — real, verified
driver.get_facts()
# raises: ConnectAuthError('SW5 rejected the credentials')

Real, verified. Any NAPALM exception, with any message, can be scripted this way -- exactly what the capstone's unreachable/auth-failed scenarios use.

Quick checkPredict output
A fixture file get_interfaces.1 contains {"exception": "napalm.base.exceptions.CommandErrorException", "args": ["unsupported command"]}. What happens when get_interfaces() is called?

What this verifies, and what it doesn't

Everything in this lesson is Category A -- genuinely executed against NAPALM's own real mock driver in this environment. The mock driver's fidelity to a specific vendor's real behavior (does a real IOS device really respond this way?) is a separate question, addressed by Category B/C boundaries throughout this module -- the mock driver is real; a real device's actual behavior is not what it verifies.

Key takeaways

  • NAPALM's 'mock' driver is a genuine, built-in library feature -- discovered directly from get_network_driver()'s own source, not something this curriculum built.
  • Fixtures are real JSON files named <path>/<method_name>.<call_count> -- verified directly from mocked_data()'s source.
  • Any method starting with get_ (plus traceroute/ping) is auto-mocked from fixtures; open()/close()/rollback() are real Python logic instead -- verified from is_mocked_method()'s source.
  • A fixture's 'exception' key scripts a real, specific NAPALM exception -- verified two ways: fail_on_open for connection failures, and an exception fixture for get_facts() failures.
  • The mock driver is real and genuinely executed (Category A) -- but it verifies the mock mechanism itself, not a real vendor device's actual behavior.