Closed umbertooo closed 7 years ago
I see two solutions:
after.insert
in isolation.I'm not sure if you really need to mock the database, so to say.
as @dmitrijs-balcers says, you don't need to mock the complete database if you want to test a callback hook. collection-hooks works, so you don't need to test its behaviour. You need to test your function. Remember that when you are unit testing, you are testing your code, not others.
So rely on collection-hooks working well, and just test your hooks.
For instance, if you want to test and after
or before
hook, you just need to test that function inside. Imagine we are adding a field on before.insert
:
const beforeInsertHook = function (userId, doc) {
doc.createdBy = userId;
};
// The test you need to run is the following
describe('beforeInsertHook', function () {
it('should add the createdAt field to the inserted document', function () {
const insertedDoc = { _id: '1', label: 'myText' };
beforeInsertHook('testUserId', doc);
expect(doc.createdBy).to.equal('testUserId');
});
});
If you need to use this
inside your test, just call the function with call
or apply
:
describe('beforeInsertHook', function () {
it('should add the createdAt field to the inserted document', function () {
const insertedDoc = { _id: '1', label: 'myText' };
const context = { transform: () => .... );
beforeInsertHook.call(context, 'testUserId', doc);
expect(doc.createdBy).to.equal('testUserId');
});
});
I wonder is it possible to refactor collection hook implementation so immutable data structures would be used. Otherwise mutating the attribute object is quite bad design I think.
It would really nice to see something like that:
const beforeInsertHook = function (userId, doc) {
return doc.set("createdBy", userId); // doc.set would return a new object just like in immutable.js
};
In such way our callbacks would be pure functions, without side effects. Which makes it more predictible and easier to test.
@dmitrijs-balcers I totally agree with you. But that would break the current API. Maybe you can write a PR on that. Or we can create a new major version on that. Or you can fork it and create your own version :smile:
I understand your point and agree with you that the callbacks should be tested in isolation, without hooks, without database. As @dmitrijs-balcers says, the database it not really required in this case. It just adds more complexity to the problem. And as the collection hooks are well tested, it is not necessary to retest it in my code.
The things you point out here are all valid, but I want to point out another thing. I currently am working on a project that uses todda00:collection-revisions
, which realizes revisions based on this package.
Now, when testing my interface, I want to create some sample data by the package todda00:collection-revisions
to be closest to the outcome I'll have as integration test.
I want to mock the database so I don't get errors because I blocked users of modifying the data outside of methods ...
I'll now just use the mocked database and call the hooks, registered by todda00:collection-revisions
manually, but it might be of interest considering this.
If anyone else is looking for this, here's what I did. Feel free to modify it ...
const update = (collection, sel, modifier, options) => {
const doc = collection.findOne(sel);
collection._hookAspects.update.before.forEach((a) => a.aspect(
null,
doc,
CollectionHooks.getFields(modifier),
modifier,
options
);
collection.update(sel, modifier, options);
}
I'm working on a project that uses collection hooks a lot. Let's say there are two collections Widgets and Activities. Widgets has a after-insert-hook to insert a new Activity-document to log the fact that a user created a new widget.
In order to test this behavior I was planning to insert a widget and search the Activities collection for the expected document to be created. As the Meteor Guide recommends, I tried https://github.com/hwillson/meteor-stub-collections with no success.
It looks like StubCollections wants to create stubs for the same functions (insert/update/...) that CollectionHooks wrapped before. Thus the stubs are without effect.
How could this be done?