Posted over 2 years ago. Visible to the public.

Ruby: Writing specs for (partially) memoized code

When you're writing specs for ActiveRecord models that use memoization, a simple #reload will not do:

Copy
it 'updates on changes' do subject.seat_counts = [5] subject.seat_total.should == 5 # seat_total is either memoized itself, or using some # private memoized method subject.seat_counts = [5, 1] subject.seat_total.reload.should == 6 # => Still 5 end

You might be tempted to manually unmemoize any memoized internal method to get #seat_total to update, but that has two disadvantages:

1) You're doing something that never happens in reality. Your tests shouldn't do things your code never does.
2) You're fiddling with internal state. When writing tests, stay on your chosen abstraction level.

Solution 1

Copy
record.unmemoize_all

Solution 2

Perform a full reload by re-finding your record:

Copy
it 'updates on changes' do subject.seat_counts = [5] subject.seat_total.should == 5 subject.seat_counts = [5, 1] # Re-find subject to wipe memoization subject = described_class.find(subject.id) subject.seat_total.reload.should == 6 # Passes end

Note that this does not work if you're testing unpersisted new records. In this case, there's probably something conceptually wrong and you either shouldn't expect to see updates or shouldn't memoize at all.

Does your version of Ruby on Rails still receive security updates?
Rails LTS provides security patches for old versions of Ruby on Rails (3.2 and 2.3).

Owner of this card:

Avatar
Dominik Schöler
Last edit:
over 2 years ago
by Henning Koch
About this deck:
We are makandra and do test-driven, agile Ruby on Rails software development.
License for source code
Posted by Dominik Schöler to makandra dev
This website uses cookies to improve usability and analyze traffic.
Accept or learn more