Rewire-Expose Private in Tests
2,461 words in 15 minutes
Here is the thing. I’m definitely a newbie in code testing. The same goes for Node.js, I bet. Although I have some former experience with development, those were all about actual implementation. Now I am doing intern at Modulus, which requires more than 80% of test coverage of code. After I finished functional part, my testing adventure started.
Problem
One problem I had is that, I got some functions in a module that called some other function directly. This makes testing hard if we want to figure out whether that function is actually called, because we are not calling the exposed function.
One way to solve it is to create an object which will include all the private functions and expose that object when under test environment. This is a very great workaround inspired by my friends and I’m now using it in my code. But that’s not what I’m going to introduce.
Introduction
Let me share the second way with you. I found this in a slide that talks about Node.js unit testing(1). So how to test private methods? The answer is using rewire module(2).
Rewire aims at easy dependency injection for Node.js unit testing. Basically, during testing, we can require rewire module and use rewire rather than require to import the file to be tested. It will be exactly the same in our test environment as under regular circumstances.
Rewire makes it possible for us to do several things:
- inject mocks for other modules or globals like process
- leak private variables
- override variables within the module
Theory
How is it possible for rewire to do that?
|
|
We can see clearly from the source code of rewire that it injects __set__ and __get__ methods while loading module. These two methods enables us to reach private variables.
Installation
|
|
Comparison
Example
Let’s say we have a file called index.js. There are two methods in it, named “someFunc” and “anotherFunc”. That someFunc is called by anotherFunc. We wanna test whether someFunc is called or not.
Workaround
So, with the workaround I mentioned above, we may create an object called private and assign all private functions as its properties. Then we can export private under test environment. When we need to call function inside module, we should do add “private.” before the name of that function.
In test file we need to hook a sinon spy(or stub) to the existing method before test. It should be restored after that.
|
|
Rewire
Let’s see how that goes with rewire.
|
|
Originally, I wanted to do something like this:
|
|
As I commented above, this won’t work due to the rigid way of binding a spy with existing method. We can only get exposed method with sinon.spy(index, 'someFunc');
, or sinon.stub(index, 'someFunc', function() {});
. Even though we can get private functions with rewire, we can’t hook it up with a spy in the original module. We could have much more progress. What a pity!
Anyways, with rewire, we don’t need to change our original code. Isn’t that great?
There are more examples on rewire’s repository on Github.
Conclusion
To make the slightest change to our code while testing, I think it would be better if we use rewire module. I’m pretty sure to use rewire for future testing, what about you?