What rspec-mocks is, and how much this app already uses it

Free preview 3 min to read

A gem that's already installed and already used

rspec-mocks ships as part of rspec-rails, the testing framework the earlier testing courses already relied on; bundle show rspec-mocks reports version 3.13.8. There's nothing to install for this course. It already runs in this app every time bundle exec rspec does.

A grep across this app's spec/ directory finds everyday use. instance_double appears in five files: dashboard_query_spec.rb, lesson_completions_spec.rb and quizzes_spec.rb, plus the course_revision tooling specs log_renderer_spec.rb and selector_spec.rb. A plain double appears in two more, pagination_helper_spec.rb and image_optimizer_spec.rb. allow(...).to receive(...) shows up in a few dozen spec files across services, requests, queries and helpers. expect(...).to receive(...) appears in four: image_optimizer_spec.rb, reorder_lesson_service_spec.rb, execution_spec.rb and the webhook delivery job's spec. None of this is hypothetical; this app's passing test suite depends on it today.

The problem this course solves

The previous course, Testing: WebMock & VCR, covered one narrow kind of fake: a fake network response standing in for an HTTP call. This course covers the general version of that idea: replacing any method call on any object, whether a service, a model or an external gem, with something fake and controlled, for the length of one test. It's also about a distinction that's commonly confused. A stub and a mock are not the same thing, and this app's specs use both, on purpose, for different reasons.

The distinction, stated up front

A stub replaces what a method returns, and doesn't care whether, or how many times, it gets called. A mock (more precisely, a message expectation) asserts that a call happened, with specific arguments and a specific number of times, and fails the test if it didn't. Both live in the same rspec-mocks gem and use closely related syntax, so mixing them up is an easy mistake. One way is reaching for a mock's assertion power when a stub's simplicity would do. The other is reaching for a stub when the whole point of the test is confirming a call happened. The next two lessons run each one in this app's Ruby process and show what happens.

What this course covers

Seven lessons, based on this app's installed rspec-mocks and its spec files. This lesson is the overview. Lesson 2 covers a stub, allow(...).to receive(...).and_return(...), which never fails however many times it's called, or whether it's called at all. Lesson 3 covers a mock, expect(...).to receive(...), which fails the test if the expected call never happens; its error message is quoted from a run. Lesson 4 covers instance_double, a double that checks each stubbed method exists on the real class, including a subtle gotcha this app's code surfaced. Lesson 5 uses this app's Enrollment::CompleteLessonService and its specs to show when stubbing a collaborator earns its place. Lesson 6 builds a tiny stub/mock object by hand, with no rspec-mocks, to show what the gem does underneath. Lesson 7 ends with a Ruby challenge that puts that hand-built version to the test.

Lesson 1 of 7 · free

Keep going with lesson 2

A stub replaces a return value, and never fails however it's called

Shows how allow replaces a return value without failing, using the stubbed ImageProcessing::Vips chain as an example.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...