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

Add support for mocking services #90

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

adamrbennett
Copy link

@adamrbennett adamrbennett commented Aug 22, 2017

  1. Create mock services in the test/bos-mocks/services directory and mock middleware in the test/bos-mocks/middleware directory. The mock file name must match the service or middleware you wish to mock.
  2. Pass comma delimited service names you wish to mock in the --mock-services command line argument and pass comma delimited middleware names you wish to mock in the --mock-middleware command line argument.

Copy link
Member

@seanpk seanpk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

var server = require('../');

// parse arguments
var argv = parseArgs(process.argv.slice(2));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does this work if invoked as blueoak-server?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks

server.init({
appDir: process.cwd()
appDir: process.cwd(),
mocks: mocks
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Author

@adamrbennett adamrbennett Aug 22, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're considering this as a foundation for future CLI, should we integrate a framework like commander instead?
(I think probably...)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that sounds much better. I might run into challenges but I'll do some exploration.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks

server.init({
appDir: process.cwd()
appDir: process.cwd(),
mocks: mocks
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. should/can the mocks directory be configurable through?
  2. can/should the list of mocks be provided through configuration?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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:

  1. To keep the config under test as similar as possible to the release/runtime config.
  2. 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.

@adamrbennett
Copy link
Author

Oops, pushed my changes before seeing your latest comments. Will address and update.


server.init({
appDir: process.cwd(),
mocks: mocks
mockServices: cli.mockServices
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would:

mocks: {
  services: cli.mockServices
}

work?

Then it can be expanded to support middleware in the future

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I like this better.

lib/loader.js Outdated
@@ -53,7 +53,7 @@ function createLoader() {
//if parent id is a consumer, i.e. was registered with a prefix,
//strip the prefix off since that's not part of the module name
parentId = parentId.indexOf('.') > -1 ? parentId.substring(parentId.indexOf('.') + 1) : parentId;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My editor added that, but lint passes so I guess it's ok?

_.includes(global.__mockServices, path.basename(id, path.extname(id)))
) {
var mockPath = path.resolve(global.__appDir, 'test', 'bos-mocks', 'services', path.basename(id));
if (mockPath) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good idea, definitely helpful.

util.launch('server6', function(output) {
assert.ok(output.indexOf('already exists') > -1);
done();
// describe('SERVER6 - duplicate service name should fail on startup', function () {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

was this exclusion meant to be temporary?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops

@adamrbennett
Copy link
Author

adamrbennett commented Aug 25, 2017

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.

@@ -180,7 +180,7 @@ function createLoader() {
var modPath = path.resolve(dir, file);
var mod;
try {
mod = require(modPath);
mod = subRequire(modPath);
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@seanpk
Copy link
Member

seanpk commented Feb 20, 2018

@adamrbennett - what are your thoughts on picking up this work again and finishing it off?
Or should we just close the PR?

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

Successfully merging this pull request may close these issues.

2 participants