ember.js - Instance initializer unit test fails with "store is undefined" -
after generating 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 following files:
models/test-data.js
import ds 'ember-data'; export default ds.model.extend({ name: ds.attr('string'), value: ds.attr( 'number' ) });
routes/index.js
import ember '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 |td|}} <li>{{td.name}}: {{td.value}}</li> {{/each}} </ul>
adapters/application.js
import restadapter 'ember-data/adapters/rest'; export default restadapter.extend({});
ember serve
runs application , displays preload data going /tests
default unit test preload
instance initializer fails error store 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 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 initialize application's store can used in unit test?
edit - tests/unit/instance-initializers/preload-test.js
import ember 'ember'; import { initialize } 'preloadtest/instance-initializers/preload'; import { module, test } 'qunit'; import destroyapp '../../helpers/destroy-app'; //import ds '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 real tests. test('it works', function(assert) { initialize(this.appinstance); // confirm results of initializer here assert.ok(true); });
tried needs: [ 'service:store' ]
, without (although suggested should not need this if ember-data on page - i've tried importing both in unit test , in instance initialiser).
versions:
ember : 2.4.5 ember data : 2.5.2
at unit test of instance-initializer, don't need real store
service. in such cases, prefer using mock services. behaviour of instance-initializer to put data store provided application. can mock store.
example test code mock service:
import ember 'ember'; import { initialize } 'preloadtest/instance-initializers/preload'; import { module, test } 'qunit'; import destroyapp '../../helpers/destroy-app'; //this 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 mock service (do not create instance, use factory) this.appinstance.register('service:store', storestubfactory); }); }, aftereach: function() { ember.run(this.appinstance, 'destroy'); destroyapp(this.application); } }); // real test: test('it works', function(assert) { initialize(this.appinstance); // confirm mock service has correct payload: assert.ok(this.appinstance.lookup('service:store').getallpayloads()); });
second option
of course can mock appinstance
paramater of initialize
function below:
import ember 'ember'; import { initialize } 'preloadtest/instance-initializers/preload'; import { module, test } 'qunit'; import destroyapp '../../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'); // real test: test('it works', function(assert) { let instance = storestubfactory.create(); initialize({lookup:function(servicename){return servicename==='service:store' ? instance : null;}}); // confirm mock service has correct payload: assert.ok(instance.getallpayloads()); });
but prefer use first one. stated instance-initializers behaviour to put data store provided application. in second option, seems checking instance-initializer calling lookup function of appinstance too. test more coupled implementation detail.
Comments
Post a Comment