Reputation: 19889
For the sake of example, suppose we're building a simple cache. We can take the functional approach using a closure:
makeCache = ->
c = {}
(key, fetch) ->
if c[key]
c[key]
else
c[key] = fetch()
c[key]
cache = makeCache()
cache(1, -> 1)
The problem I find with this approach is that you can't test it easily. I want to be able to check that the '1'
is in the cache. If I add more values, I want to make sure they are in the cache as well.
If I have a more complicated cache, like an LRU cache, I would want to test other aspects as well. However those variables are entirely hidden behind a closure.
I tend to think up solutions using a closures but then I resort to an object oriented style so that its testable:
class Cache
constructor: ->
@c = {}
get: (key, fetch) ->
if c[key]
c[key]
else
c[key] = fetch()
c[key]
cache = new Cache()
cache.get(1, ->1)
Now I have access to cache.c
and any other variables that I need to inspect to test.
So my question is, how can you test your code when using a functional style closure?
Upvotes: 0
Views: 43
Reputation: 50807
Would this not test for your specific case?
cache = new Cache()
cache.get(1, ->1)
expect(cache.get(1, ->0)).toBe(1);
The more general problem is real enough. But it's true with any encapsulation technique. I would argue, though, that the whole goal of testing, or at least of unit testing, is to work the public interface of a system. So if you don't have a public facility to check whether something is in the cache, then you don't need a unit test for it.
There are certainly people who disagree with this, but I find it a bright dividing line.
Upvotes: 2