I think I finally came to a reasonable conclusion. Let me share with you what, in my opinion, might be the best way to approach unit testing services that rely on the store.
The answer really lies in the assumption that we must make when writing unit tests . That is, everything that is outside of our logical unit should be considered correct, and our units must be completely independent.
Thus, when servicing a store, it is best to create a stub or mock (see this question to understand the difference between a layout and a stub) for a store. The stop for the store itself is quite simple. Something like this will do:
store: { find: function() { var mockedModel = Ember.Object.create({}); return mockedModel; }, query: ... }
If you prefer to use the layout instead, you can do something like the following (I did it very quickly so that it does not work completely, but it is enough to convey the idea):
import Ember from 'ember'; class MockStore { constructor() { this.models = Ember.A([]); } createRecord(modelName, record) { // add a save method to the record record.save = () => { return new Ember.RSVP.Promise((resolve) => { resolve(true); }); }; if (!this.models[modelName]) { this.models[modelName] = Ember.A([]); } this.models[modelName].pushObject(record); return record; } query(modelName, query) { let self = this; return new Ember.RSVP.Promise((resolve) => { let model = self.models[modelName]; // find the models that match the query let results = model.filter((item) => { let result = true; for (let prop in query) { if (query.hasOwnProperty(prop)) { if (!item[prop]) { result = false; } else if (query[prop] !== item[prop]) { result = false; } } } return result; }); resolve(results); }); } } export default MockStore;
Further, all you need to do is set the repository property (or any other access to it) to your service in a new instance of the mock store when you run the test. I did it like this:
import Ember from 'ember'; import { moduleFor, test } from 'ember-qunit'; import MockStore from '../../helpers/mock-store'; let session; let store; const username = ''; const password = ''; moduleFor('service:authentication', 'Unit | Service | authentication', { beforeEach() { session = Ember.Object.create({}); store = new MockStore(); } }); test('it should authenticate the user', function (assert) {
The documentation for testing these situations is definitely unsatisfactory, so there may be a better method, but I'll work on that now. Also, if you look at the Discourse project that uses ember, they follow the same pattern described here, but in a slightly more advanced way.