mfncooper / mockery

Simplifying the use of mocks with Node.js
Other
1.1k stars 60 forks source link

Mocking across tests #4

Closed BryanDonovan closed 12 years ago

BryanDonovan commented 12 years ago

Hi Martin,

I don't think this is necessarily an issue with Mockery, but I'm having a hard time finding a good solution for this problem. The problem is that if I run one test that requires a real module, and then run another that mocks that same module, the mocked version fails (the reverse is also seems to be true but I'm having a hard time proving it). This is only a problem when a test runner loads all the test files at once, which caches the require paths and mockery gets bypassed (or something).

I've simplified the problem into a standalone git repo here:

https://github.com/BryanDonovan/nodejs-mock-test

If you have a chance to take a look, I'd really appreciate it. It might just be something obvious that I'm doing wrong.

Thanks, Bryan

mfncooper commented 12 years ago

You're right, it's not a Mockery issue, it's just the Node module loader tripping you up by doing its usual caching.

You can easily work around this with Mockery by taking advantage of the unhooking feature. What you do is modify the non mock test case to register 'foo' as allowable and request that it be unhooked. That way, 'foo' will be loaded independently by each test case. (It's probably safest to also modify the allowable registration in the mock test to unhook, so that test order doesn't matter.)

You could also modify only the mocking test case, but you'd have to mess with the require cache manually, which is a bit messy because you need to call a module loader function to resolve the path to 'foo' first.

Here's a diff:

diff --git a/test/no_mock.unit.js b/test/no_mock.unit.js
index dffdefe..5aaedbe 100644
--- a/test/no_mock.unit.js
+++ b/test/no_mock.unit.js
@@ -1,7 +1,20 @@
 var assert = require('assert');
-var foo = require('../lib/foo');
+var mockery = require('mockery');
+
+var foo;

 describe("no mock", function() {
+    before(function() {
+        mockery.enable();
+        mockery.registerAllowable('../lib/foo', true);
+        foo = require('../lib/foo');
+    });
+
+    after(function() {
+        mockery.disable();
+        mockery.deregisterAll();
+    });
+
     it("returns real response", function(done) {
         var result = foo.get_widget();
         assert.equal(result, 'real widget');
BryanDonovan commented 12 years ago

Thanks Martin, that works.