Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Runtime error when using mock-fs and express.js body-parser #47

Open
mlenkeit opened this issue Jun 28, 2015 · 3 comments
Open

Runtime error when using mock-fs and express.js body-parser #47

mlenkeit opened this issue Jun 28, 2015 · 3 comments

Comments

@mlenkeit
Copy link

I'm testing my express.js middleware with mock-fs to mock files that should be read or written.

It seems that using mock-fs in my tests breaks the express.js body-parser package.

I created a Gist to reproduce the issue: https://gist.github.com/mlenkeit/a6fa3960967b3fa6a165
Simply clone the Gist, run npm install followed by npm test. The tests will fail somewhere deep in the body-parser package. If you comment mocking the filesystem in the Gist (lines 19 and 23) and run the tests again, everything works fine.

I attached a stack trace (which doesn't include any sign of mock-fs).

Stack trace:

Error: specified encoding unsupported
    at makeError (c:\github\a6fa3960967b3fa6a165\node_modules\body-parser\node_modules\raw-body\index.js:184:15)
    at getDecoder (c:\github\a6fa3960967b3fa6a165\node_modules\body-parser\node_modules\raw-body\index.js:156:15)
    at module.exports (c:\github\a6fa3960967b3fa6a165\node_modules\body-parser\node_modules\raw-body\index.js:75:15)
    at read (c:\github\a6fa3960967b3fa6a165\node_modules\body-parser\lib\read.js:62:3)
    at urlencodedParser (c:\github\a6fa3960967b3fa6a165\node_modules\body-parser\lib\types\urlencoded.js:83:5)
    at Layer.handle [as handle_request] (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:312:13)
    at c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:280:7
    at Function.process_params (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:330:12)
    at next (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:271:10)
    at expressInit (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\middleware\init.js:33:5)
    at Layer.handle [as handle_request] (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:312:13)
    at c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:280:7
    at Function.process_params (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:330:12)
    at next (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:271:10)
    at query (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\middleware\query.js:38:5)
    at Layer.handle [as handle_request] (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:312:13)
    at c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:280:7
    at Function.process_params (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:330:12)
    at next (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:271:10)
    at Function.handle (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\router\index.js:176:3)
    at EventEmitter.handle (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\application.js:173:10)
    at Server.app (c:\github\a6fa3960967b3fa6a165\node_modules\express\lib\express.js:38:9)
    at Server.emit (events.js:110:17)
    at HTTPParser.parserOnIncoming [as onIncoming] (_http_server.js:491:12)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:111:23)
    at Socket.socketOnData (_http_server.js:343:22)
    at Socket.emit (events.js:107:17)
    at readableAddChunk (_stream_readable.js:163:16)
    at Socket.Readable.push (_stream_readable.js:126:10)
mlenkeit added a commit to mlenkeit/animated-octo-sansa that referenced this issue Jun 28, 2015
the mock-fs package appears to interfere with some other packages, e.g.
this, the filesystem is only mocked when required.

see also tschaub/mock-fs#47
@tschaub
Copy link
Owner

tschaub commented Jun 29, 2015

Thanks for the report @mlenkeit. I'll try to take a look soon. Any chance you checked what encoding was passed to raw-body?

mlenkeit added a commit to mlenkeit/animated-octo-sansa that referenced this issue Jun 30, 2015
unfortunately, the mock-fs package was conflicting with some other
packages. also, I didn't find any api for accessing the current content of
a mocked file without going through fs.readFile. so the package was
replaced by the rewire package and some custom mock fs coding. works like
a charm 😄

for mock-fs conflict, see tschaub/mock-fs#47
@andyault
Copy link

andyault commented Dec 29, 2017

Sorry for bumping such an old issue, but I was running into the same problem (although with a different error) as the OP. I'm trying to use supertest to test an express server, and was receving this error:

Error: ENOENT, no such file or directory 'myproject/node_modules/iconv-lite/encodings'
    at Binding.<anonymous> (myproject/node_modules/mock-fs/lib/binding.js:1060:13)
    at maybeCallback (myproject/node_modules/mock-fs/lib/binding.js:42:17)
    at Binding.lstat (myproject/node_modules/mock-fs/lib/binding.js:1057:10)
    at Object.realpathSync (fs.js:1659:15)
    at toRealPath (module.js:143:13)
    at tryFile (module.js:139:22)
    at tryExtensions (module.js:151:22)
    at Function.Module._findPath (module.js:218:18)
    at Function.Module._resolveFilename (module.js:483:25)
    at Function.Module._load (module.js:437:25)
    at Module.require (module.js:513:17)
    at require (internal/module.js:11:18)
    at Object.getCodec (myproject/node_modules/iconv-lite/lib/index.js:65:27)
    at Object.getDecoder (myproject/node_modules/iconv-lite/lib/index.js:122:23)
    at getDecoder (myproject/node_modules/raw-body/index.js:45:18)
    at readStream (myproject/node_modules/raw-body/index.js:180:15)
    at getRawBody (myproject/node_modules/raw-body/index.js:108:12)
    at read (myproject/node_modules/body-parser/lib/read.js:77:3)
    at jsonParser (myproject/node_modules/body-parser/lib/types/json.js:134:5)
    at Layer.handle [as handle_request] (myproject/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (myproject/node_modules/express/lib/router/index.js:317:13)
    at myproject/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (myproject/node_modules/express/lib/router/index.js:335:12)
    at next (myproject/node_modules/express/lib/router/index.js:275:10)
    at urlencodedParser (myproject/node_modules/body-parser/lib/types/urlencoded.js:100:7)
    at Layer.handle [as handle_request] (myproject/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (myproject/node_modules/express/lib/router/index.js:317:13)
    at myproject/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (myproject/node_modules/express/lib/router/index.js:335:12)
    at next (myproject/node_modules/express/lib/router/index.js:275:10)
    at expressInit (myproject/node_modules/express/lib/middleware/init.js:40:5)
    at Layer.handle [as handle_request] (myproject/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (myproject/node_modules/express/lib/router/index.js:317:13)
    at myproject/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (myproject/node_modules/express/lib/router/index.js:335:12)
    at next (myproject/node_modules/express/lib/router/index.js:275:10)
    at query (myproject/node_modules/express/lib/middleware/query.js:45:5)
    at Layer.handle [as handle_request] (myproject/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (myproject/node_modules/express/lib/router/index.js:317:13)
    at myproject/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (myproject/node_modules/express/lib/router/index.js:335:12)
    at next (myproject/node_modules/express/lib/router/index.js:275:10)
    at Function.handle (myproject/node_modules/express/lib/router/index.js:174:3)
    at Function.handle (myproject/node_modules/express/lib/application.js:174:10)
    at Server.app (myproject/node_modules/express/lib/express.js:39:9)
    at emitTwo (events.js:125:13)
    at Server.emit (events.js:213:7)
    at parserOnIncoming (_http_server.js:602:12)
    at HTTPParser.parserOnHeadersComplete (_http_common.js:116:23)

This error seems to be coming from express body-parser requiring files for encoding (as you seem to already know). As a super quick fix, I was able to come up with this function to un-mock a directory:

let readdir = function(dirPath) {
	let ret = {};
	let files = fs.readdirSync(dirPath);

	for(let file of files) {
		let fullPath = path.join(dirPath, file);

		try {
			ret[file] = fs.readFileSync(fullPath);
		} catch(err) {
			if(err.code === 'EISDIR')
				ret[file] = readdir(fullPath)
			else
				throw err;
		}
	}

	return ret;
}

let encodingsPath = path.join(__dirname, '../node_modules/iconv-lite/encodings');
let encodings = readdir(encodingsPath);

mock({
	... files to mock ...
	[encodingsPath]: encodings
});

and all is well. Although this is not ideal, it seems that (at least in my case) it's necessary. Would a mock.Ignore or mock.Exclude function be something worth adding?

@savvyer
Copy link

savvyer commented Jul 23, 2018

Easier workaround to that problem is to preload the encodings module before mocking a filesystem:

const encodings = require('iconv-lite/encodings');

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants