Chet
Chet

Reputation: 19889

Writing tests for functional code?

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

Answers (1)

Scott Sauyet
Scott Sauyet

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

Related Questions