# How to Mock `redis` datastore  

Mocking and stubbing walk hand in hand. stubbing `redis` pub/sub, a datastore widely adopted in `nodejs` ecosystem, can be a setback when testing WebSocket endpoints. This article brings clarity, and a path forward, to it.  

***In this article we will talk about:*** 

- Stubbing `redis` clients 
- Replacing a `redis` with a _drop in replacement_. 
- How to avoid spin-up a `redis` server. 

> Even though this blog post was designed to offer complementary materials to those who bought my **_[Testing `nodejs` Applications book](https://bit.ly/2ZFJytb)_**, the content can help any software developer to tuneup working environment. **_[You use this link to buy the book](https://bit.ly/2ZFJytb)_**.  [![Testing nodejs Applications Book Cover](https://snap.as/a/42OS2vs.png)](https://bit.ly/2ZFJytb)

## Show me the code

```JavaScript 
module.exports = function(req, res, next){
  User.findById(req.user, (error, next) => {
    if(error) return next(error); 
    new Messenger(options).send().then((response) => {
      redisClient.publish(Messenger.SYSTEM_EVENT, payload));
      //schedule a delayed job 
      return res.status(200).json({message: 'Some Message'});
    });
  });
};

//service based equivalent using a service layer
module.exports = function(req, res, next){
  UserService.findById(req.user)
    .then(new Messenger(options).send())
    .then(new RedisService(redisClient).publish(Messenger.SYSTEM_EVENT, payload))
    .then(response => res.status(200).json(message);})
    .catch(error => next(error));
};

```

> The use of arrow functions instead of function keyword serves to shorten the code. It is possible to replace all arrow functions with the `function` keywords, for readability. 

## What can possibly go wrong?

The following points may be a challenge to mock datastore access:

- Same level of challenge as when mocking database access functions
- Asynchronous nature of pub/sub clients, characteristic to queue processing systems 
- When the application is using `redis` (local or remote)
- Running tests without spinning up a `redis` server 

The following sections will explore more on making points stated above work. 

## Show me the tests

>   There is more than one way to go with mocking. I have to preview 3 libraries and choose one the fits better my needs.  

Some of libraries are we can tap into to make mocking possible are : `rewire`, `fakeredis`, `proxywire` and  `sinon`. 

Mocking `redis` using `rewire`

```JavaScript
var Rewire = require('rewire');
//module to mock redisClient from 
var controller = Rewire("/path/to/controller.js");
//the mock object + stubs
var redisMock = {
  //get|pub|sub are stubs that can return promise|or do other things
  get: sinon.spy(function(options){return "someValue";});
  pub: sinon.spy(function(options){return "someValue";});
sub: sinon.spy(function(options){return "someValue";});
};
//replacing --- `redis` client methods :::: this does not prevent spinup a new `redis` server
controller.__set__('redisClient', redisMock);
```
_*Example*:_


Mocking `redis` using `fakeredis`. `fakeredis` provides an thrown in replacement and functionalities for `redis`'s `createClient()` function.  

```JavaScript
var redis = require("redis");    
var fakeredis = require('fakeredis'); 
var sinon = require('sinon'); 
var assert = require('chai').assert; 

var users, client; 
describe('redis', function(){
  before(function(){
    sinon.stub(redis, 'createClient', , fakeredis.createClient);
    client = redis.createClient(); //or anywhere in code it can be initialized
  });

  after(function(done){
    client.flushdb(function(error){
      redis.createClient.restore();
      done();
    });
  });
});
```
_*Example*:_


Two of the alternatives whose examples are not figuring in this article are mocking `redis` using`redis-mock` and `proxyquire`.
  
>   _The goal of the `redis-mock` project is to create a feature-complete mock of [`redis_node`](https://github.com/mranney/node_redis), so that it may be used interchangeably when writing unit tests for code that depends on `redis`_

## Conclusion

In this article, we revisited strategies to mock `redis` access methods and replace response objects with mock data.

Testing in parallel can stress the `redis` server. Mocking `redis` clients makes tests faster, reduces friction on the network, and prevent stressing `redis` server especially when shared with other production applications. 

There are additional complimentary materials in the __"Testing `nodejs` applications"__ book.

## References 

- [Testing `nodejs` Applications book](https://bit.ly/2ZFJytb)
- Faking `redis` in `nodejs` with `fakeredis` ~ [`fakeredis` package homepage](https://www.npmjs.com/package/fakeredis) ~ a tutorial.
- [`redis` mock](https://github.com/faeldt/redis-mock) ~ first library I looked into. 
- Mock `redis` Client, then stub function with `sinon` ~ rewire ~ [StackOverflow Answer](https://stackoverflow.com/a/29222051/132610)
- `rewire` ~ Easy monkey-patching for `nodejs` unit tests ~ [Github Rewire Library](https://github.com/jhnns/rewire)
- `proxyquire` ~ Proxies `nodejs` require in order to allow overriding dependencies during testing [Github Library](https://github.com/thlorenz/proxyquire)



#snippets #code #annotations #question #discuss