Add support for mocking services#90
Conversation
seanpk
left a comment
There was a problem hiding this comment.
I really like this initiative.
I've requested some changes, but am open to discussion on those each point. Hopefully, however, they all make sense.
bin/blueoak-server.js
Outdated
| var server = require('../'); | ||
|
|
||
| // parse arguments | ||
| var argv = parseArgs(process.argv.slice(2)); |
There was a problem hiding this comment.
does this work if invoked as blueoak-server?
There was a problem hiding this comment.
You mean like this?
blueoak-server --mocks mock-service
Instead of like this?
./node_modules/blueoak-server/bin/blueoak-server.js --mocks mock-service
Yes, it works on Node v6.8.1
bin/blueoak-server.js
Outdated
| server.init({ | ||
| appDir: process.cwd() | ||
| appDir: process.cwd(), | ||
| mocks: mocks |
There was a problem hiding this comment.
maybe we should have a different script/invocation that supports mocks instead of adding testing support directly into the main command ...
say bin/bos-mock.js
There was a problem hiding this comment.
Yeah, I know what you mean. My initial preference was to avoid modifying the main script, but I figured it doesn't add much overhead, and it might be nice to parse other CLI args in the future.
I took this approach for the simplicity and it lends itself well to Dockerization. With ENTRYPOINT ["blueoak-server"] arguments can be passed to the container at the command line more simply. For example, docker run blueoak-server --mocks mock-service instead of docker run --entrypoint bin/bos-mock.js blueoak-server --mocks mock-service
There was a problem hiding this comment.
If we're considering this as a foundation for future CLI, should we integrate a framework like commander instead?
(I think probably...)
There was a problem hiding this comment.
Yep, commander provides a better UX with usage output.
| */ | ||
| exports.init = function(logger) { | ||
| logger.info('Dummy Service Mock initialized'); | ||
| process.exit(0); // exit test here |
There was a problem hiding this comment.
I think it would be a better test for the dummy service not to exit, but to provide a function that can be called from the test after server startup has completed
There was a problem hiding this comment.
Yeah that sounds much better. I might run into challenges but I'll do some exploration.
bin/blueoak-server.js
Outdated
| server.init({ | ||
| appDir: process.cwd() | ||
| appDir: process.cwd(), | ||
| mocks: mocks |
There was a problem hiding this comment.
since mocks are used for testing/prototyping, I think it would make sense that their default directory is tests/mocks, or tests/bos-mocks/, or even tests/bos-mocks/services if it would ever make sense to have mocks for middleware or handlers (which it might)
There was a problem hiding this comment.
Totally agree. Good point about mocking the other things. Only concern would be potential collisions with existing projects that already have test/s directories. While I prefer tests/mocks, I think tests/bos-mocks is far less likely to collide with code in existing projects.
There was a problem hiding this comment.
yeah ... and it looks like test/bos-mocks is the way to go since the template project has a test dir, not a tests dir
which makes me think:
- should/can the mocks directory be configurable through?
- can/should the list of mocks be provided through configuration?
There was a problem hiding this comment.
I could add a config to define the location of mocks, but I initially chose not to because BOS appears to favor convention over configuration for the locations of other things like handlers, services, etc.
I avoided declaring mocks in the configuration for the following reasons:
- To keep the config under test as similar as possible to the release/runtime config.
- To be able to easily control which services are mocked without changing config (i.e.: mocks won't be loaded simply because they exist or are declared, but only if they're also identified in the CLI argument). Although, this approach could still apply if mocks are declared in config.
Let me know how you'd like to proceed here and I'll make the necessary updates.
|
Oops, pushed my changes before seeing your latest comments. Will address and update. |
bin/blueoak-server.js
Outdated
| server.init({ | ||
| appDir: process.cwd(), | ||
| mocks: mocks | ||
| mockServices: cli.mockServices |
There was a problem hiding this comment.
would:
mocks: {
services: cli.mockServices
}work?
Then it can be expanded to support middleware in the future
lib/loader.js
Outdated
| //strip the prefix off since that's not part of the module name | ||
| parentId = parentId.indexOf('.') > -1 ? parentId.substring(parentId.indexOf('.') + 1) : parentId; | ||
|
|
||
There was a problem hiding this comment.
whitespace (I can't recall if this project has the requirement to strip trailing whitespace ... I may just be used to seeing that in other code)
There was a problem hiding this comment.
My editor added that, but lint passes so I guess it's ok?
lib/subRequire.js
Outdated
| _.includes(global.__mockServices, path.basename(id, path.extname(id))) | ||
| ) { | ||
| var mockPath = path.resolve(global.__appDir, 'test', 'bos-mocks', 'services', path.basename(id)); | ||
| if (mockPath) { |
There was a problem hiding this comment.
on failure to find the service, would a message be helpful?
maybe like:
logger.warn(util.format('the requested mock service "%s" was not found in the mock service directory (%s)', mockDir, mockId));(assuming the mock directory has been calculated once into a variable named mockDir and mockId = path.basename(id) was done too ... util.format should be used for safety since users can configure different loggers)
There was a problem hiding this comment.
Good idea, definitely helpful.
test/integration/testLoader.js
Outdated
| util.launch('server6', function(output) { | ||
| assert.ok(output.indexOf('already exists') > -1); | ||
| done(); | ||
| // describe('SERVER6 - duplicate service name should fail on startup', function () { |
There was a problem hiding this comment.
was this exclusion meant to be temporary?
|
I just went ahead and added support for mocking middleware to expose and address all the gremlins now. We're not waiting on this PR anymore on dependent projects, so no rush to merge -- let's get it right. |
| var mod; | ||
| try { | ||
| mod = require(modPath); | ||
| mod = subRequire(modPath); |
There was a problem hiding this comment.
Middleware mocks were not loading because middleware was not loaded with subRequire. I did this to make it work, but admittedly do not understand all of the potential ramifications of this change.
|
@adamrbennett - what are your thoughts on picking up this work again and finishing it off? |
test/bos-mocks/servicesdirectory and mock middleware in thetest/bos-mocks/middlewaredirectory. The mock file name must match the service or middleware you wish to mock.--mock-servicescommand line argument and pass comma delimited middleware names you wish to mock in the--mock-middlewarecommand line argument.