After generating an example application:
ember new preloadtest
cd preloadtest/
ember g instance-initializer preload
ember g model test-data
ember g route index
ember g adapter application
With the following files:
models/test-data.js
import DS from 'ember-data';
export default DS.Model.extend({
name: DS.attr('string'),
value: DS.attr( 'number' )
});
routes/index.js
import Ember from 'ember';
export default Ember.Route.extend({
model(){
return this.store.peekAll( 'test-data' );
}
});
instance-initializers/preload.js
export function initialize( appInstance ) {
let store = appInstance.lookup( 'service:store' );
store.pushPayload( { "testDatas": [
{ "id": 1, "name": "aaa", "value": 1},
{ "id": 2, "name": "bbb", "value": 2},
{ "id": 3, "name": "ccc", "value": 3}
] } );
}
export default {
name: 'preload',
initialize
};
templates/index.hbs
<ul>
{{#each model as |td|}}
<li>{{td.name}}: {{td.value}}</li>
{{/each}}
</ul>
adapters/application.js
import RESTAdapter from 'ember-data/adapters/rest';
export default RESTAdapter.extend({});
ember serve
runs the application and displays the preload data but going to /tests
the default unit test for the preload
instance initializer fails with the error store is undefined
.
Full Error Message:
Died on test #1 @http://localhost:4200/assets/tests.js:212:1
Module.prototype.exports@http://localhost:4200/assets/vendor.js:94:20
Module.prototype.build@http://localhost:4200/assets/vendor.js:142:5
findModule@http://localhost:4200/assets/vendor.js:193:5
requireModule@http://localhost:4200/assets/vendor.js:181:12
TestLoader.prototype.require@http://localhost:4200/assets/test-loader.js:67:9
TestLoader.prototype.loadModules@http://localhost:4200/assets/test-loader.js:58:13
TestLoader.load@http://localhost:4200/assets/test-loader.js:89:7
@http://localhost:4200/assets/test-support.js:6397:5
: store is undefined@ 114 ms
Source:
initialize@http://localhost:4200/assets/preloadtest.js:213:5
@http://localhost:4200/assets/tests.js:213:1
runTest@http://localhost:4200/assets/test-support.js:2716:14
Test.prototype.run@http://localhost:4200/assets/test-support.js:2701:4
run/<@http://localhost:4200/assets/test-support.js:2843:6
process@http://localhost:4200/assets/test-support.js:2502:4
begin@http://localhost:4200/assets/test-support.js:2484:2
resumeProcessing/<@http://localhost:4200/assets/test-support.js:2544:4
How do I initialize the application's store so that it can be used in the unit test?
Edit - tests/unit/instance-initializers/preload-test.js
import Ember from 'ember';
import { initialize } from 'preloadtest/instance-initializers/preload';
import { module, test } from 'qunit';
import destroyApp from '../../helpers/destroy-app';
//import DS from 'ember-data';
module('Unit | Instance Initializer | preload', {
//needs: [ 'service:store' ],
beforeEach: function() {
Ember.run(() => {
this.application = Ember.Application.create();
this.appInstance = this.application.buildInstance();
});
},
afterEach: function() {
Ember.run(this.appInstance, 'destroy');
destroyApp(this.application);
}
});
// Replace this with your real tests.
test('it works', function(assert) {
initialize(this.appInstance);
// you would normally confirm the results of the initializer here
assert.ok(true);
});
Tried it with needs: [ 'service:store' ]
and without (although its suggested that you should not need to do this if Ember-Data is on the page - which I've also tried importing both in the unit test and in the instance initialiser).
Versions:
Ember : 2.4.5
Ember Data : 2.5.2
At Unit test of an instance-initializer, you don't need to get real store
service. In such cases, prefer using mock services. The behaviour of your instance-initializer is to put some data to the store which is provided by application. You can easily mock that store.
Example test code with mock service:
import Ember from 'ember';
import { initialize } from 'preloadtest/instance-initializers/preload';
import { module, test } from 'qunit';
import destroyApp from '../../helpers/destroy-app';
//this is the mock store service:
const storeStubFactory = Ember.Service.extend({
data: null,
init(){
this.data = [];
},
pushPayload(payload){
this.get('data').pushObject(payload);
},
getAllPayloads(){
return this.get('data');
}
});
module('Unit | Instance Initializer | preload', {
beforeEach: function() {
Ember.run(() => {
this.application = Ember.Application.create();
this.appInstance = this.application.buildInstance();
//Register your mock service (do not create instance, use factory)
this.appInstance.register('service:store', storeStubFactory);
});
},
afterEach: function() {
Ember.run(this.appInstance, 'destroy');
destroyApp(this.application);
}
});
// This is your real test:
test('it works', function(assert) {
initialize(this.appInstance);
// confirm that mock service has the correct payload:
assert.ok(this.appInstance.lookup('service:store').getAllPayloads());
});
Second option
Of course you can also mock the appInstance
paramater of the initialize
function as below:
import Ember from 'ember';
import { initialize } from 'preloadtest/instance-initializers/preload';
import { module, test } from 'qunit';
import destroyApp from '../../helpers/destroy-app';
const storeStubFactory = Ember.Service.extend({
data: null,
init(){
this.data = [];
},
pushPayload(payload){
this.get('data').pushObject(payload);
},
getAllPayloads(){
return this.get('data');
}
});
module('Unit | Instance Initializer | preload');
// This is your real test:
test('it works', function(assert) {
let instance = storeStubFactory.create();
initialize({lookup:function(serviceName){return serviceName==='service:store' ? instance : null;}});
// confirm that mock service has the correct payload:
assert.ok(instance.getAllPayloads());
});
But I prefer to use first one. We stated that your instance-initializers behaviour as to put some data to the store which is provided by application. But in second option, it seems that we are also checking that your instance-initializer is calling the lookup function of appInstance too. This test is more coupled to your implementation detail.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With