Testing Without Mocks Example
This project demonstrates the ideas in James Shore's Testing Without Mocks pattern language.
About the Program
The program is a simple ROT-13 command-line tool. To use, run
node src/run.js "text to convert". The ROT-13 output will be displayed on the command-line. For example:
$ node src/run.js "Hello World" Uryyb Jbeyq
The program consists of three files, all in the
run.js- application entry point; no meaningful code
app.js- Application Layer code that coordinates between command-line infrastructure and ROT-13 logic.
command_line.jsInfrastructure Layer code that wraps command-line variables (
process.argv)and output (
About the Patterns
The purpose of this program is to demonstrate the Testing Without Mocks ideas. The following patterns are present:
The code is tested entirely with narrow tests that each test a subset of the application.
_app_test.jstests the Application Layer code and the way it uses the command-line infrastructure, but it doesn't test the command-line infrastructure itself (
console). It uses Nullable Infrastructure, Configurable Responses, and Send State to do this (see below).
_command_line_test.jstests the Infrastructure Layer code and the way it uses
console. It uses Focused Integration Tests to do this (see below).
There are no broad integration tests (end-to-end tests), but
_command_line_test.js overlap to provide the same safety net that broad tests do. The one gap is
run.js, which could be covered by a smoke test. (But it's so simple it's hard to imagine it breaking.)
The code is too simple to have a proper A-Frame architecture, but it's simulated by putting the rot13 logic in a separate function.
The Application Layer code (
app.js) coordinates logic and infrastructure by reading from infrastructure, passing the data to the logic function, and then writing to infrastructure.
The application was built using evolutionary design, starting with a single file. (See the commit history.)
Object constructors don't do any significant work.
Command-line infrastructure is wrapped by
The Infrastructure Layer tests in
_command_line_test.js check that
command_line.js actually integrates properly with
CommandLine.createNull() creates a Null version of CommandLine that operates just like the real thing, except it doesn't actually read or write to the command line. This is used by the Application Layer tests in
createNull() is implemented with private stubs of
console. (Those stubs can be found at the bottom of
CommandLine.createNull("my_response") will cause it to say that the program's command-line argument is "my_response". This is used by the Application Layer tests in
After sending output to the console, you can see what was sent by calling
commandLine.getLastOutput(). This is used by the Application Layer tests in