Ulysse BN
Ulysse BN

Reputation: 11396

Test cached (multiprocessed) and memoized method

Short question, I'd like to test this method foo:

class MyClass
    def foo
        # The `@cache_key` is defined by instance but can be the same for
        # different instances (obviously I guess)
        @foo ||= cache.fetch(@cache_key) do
            # call a private method, tested aside
            generate_foo_value || return
            # The `|| return` trick is one I use to skip the yield result
            # in case of falsey value. May not be related to the question,
            # but I left it there because I'm not so sure.
        end
   end
end

The issue here is that I have two kinds of caching.

On one hand, I have @foo ||= that assure memoization and that I can test pretty easily. For instance by calling twice my method and watch if the result is different.

On the other hand, I have the cache.fetch method which may be shared between different instances. The trouble for me is here: I don't know the best way to unit test it. Should I mock my cache? Should I watch cache result? Or should I run plural instances with the same cache key?

And for this last question, I don't know how to run plural instances easily using rspec.

Upvotes: 1

Views: 273

Answers (1)

Greg
Greg

Reputation: 6628

I don't think you need plural instances in this case. It looks like you could just set the cache value in the specs and test that the MyClass instance(s) is returning it.

before { cache.set(:cache_key, 'this is from cache') }
subject { MyClass.new(:cache_key, cache) } # you didn't provide the
                                           # initializer, so I'll just assume
                                           # that you can set the cache key 
                                           # and inject the cache object 

specify do 
  expect(subject.foo).to eq 'this is from cache'
end

You can also set the expectation that generate_foo_value is not run at all in this case.

My reasoning is that: you don't need to fully emulate setting the cache in a separate process. You test only that if the cache with the key is set - your method has to return it instead of doing expensive computation.

The fact that this cache is shared between processes (like it sits in a PostgreSQL DB, or Redis or whatever) is irrelevant for the test.

Upvotes: 1

Related Questions