You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: README.md
+110Lines changed: 110 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1202,6 +1202,116 @@ export default new VueRouter({
1202
1202
});
1203
1203
```
1204
1204
1205
+
## Mocking actions, mutations and getters
1206
+
There still can be a scenario when using real store might be a problem and you would like to mock some parts. Mocking an action can be achieved by stubbing the dispatch function provided by the store:
1207
+
```js
1208
+
beforeEach(function () {
1209
+
let dispatchStub =sinon.stub(this.store, ['dispatch']);
1210
+
dispatchStub.callThrough(); // allow other actions to be executed
1211
+
dispatchStub.withArgs('auth/login').resolves(42); // only if dispatch has been invoked for 'auth/login' then return resolved Promise with custom result
1212
+
});
1213
+
1214
+
it('should do something', function () {
1215
+
let result =this.store.dispatch('something');
1216
+
expect(result).to.become(/* original call result */);
1217
+
1218
+
result =this.store.dispatch('auth/login');
1219
+
expect(result).to.become(42);
1220
+
});
1221
+
```
1222
+
1223
+
Mutations are very similar to actions, but instead of dispatch, we are going to stub commit:
1224
+
```js
1225
+
beforeEach(function () {
1226
+
let commitStub =sinon.stub(this.store, ['commit']);
1227
+
commitStub.callThrough(); // allow other mutations to be executed
1228
+
commitStub.withArgs('setToken').callsFake(x=> x);
1229
+
});
1230
+
1231
+
it('should do something', function () {
1232
+
let result =this.store.commit('something');
1233
+
expect(result).to.become(/* original call result */);
1234
+
1235
+
result =this.store.commit('setToken', 'random_token');
1236
+
expect(result).to.equal('random_token');
1237
+
});
1238
+
```
1239
+
Getters are little bit tougher and they completely resist any attempt to override them. Getters are unfortunately configured as non-configurable when store is created. That means attempts like these won't help us:
1240
+
```js
1241
+
beforeEach(function () {
1242
+
this.store.getters.isAuthenticated=sinon.stub(); // throws an Error
}); // returns false, which means it wasn't successful
1255
+
});
1256
+
```
1257
+
It's not over yet, the `getters` property is not protected, that means we can replaced whole `getters` with mock which we can control over. We can use [Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy) as a man-in-the-middle which will be returning mocked getters or original ones based on the configuration:
1258
+
```js
1259
+
beforeEach(function () {
1260
+
let isAuthenticatedStub =sinon.stub().returns(true);
1261
+
1262
+
let proxy =newProxy(this.store.getters, {
1263
+
get(getters, key) {
1264
+
if (key ==='isAuthenticated') {
1265
+
returnisAuthenticatedStub();
1266
+
} else {
1267
+
return getters[key];
1268
+
}
1269
+
}
1270
+
});
1271
+
1272
+
Object.defineProperty(this.store, 'getters', {
1273
+
get() {
1274
+
return proxy;
1275
+
}
1276
+
});
1277
+
});
1278
+
```
1279
+
That's a lot of code for mocking only one getter so it would be better to extract it as a helper method or attach it to the `Store.prototype`. We can also make the name and the stub function's parameters so the function becomes more generic:
You can see full implementation (including restoring mock back to original functionality) in [test/unit/utils/store.js](./test/unit/utils/store.js) file.
1314
+
1205
1315
# Using flush-promises vs Vue.nextTick()
1206
1316
1207
1317
This topic has been fully covered by [the official documentation](https://vue-test-utils.vuejs.org/en/guides/testing-async-components.html).
0 commit comments