Ok! Let's move to our Pomodoro application! By the way, when was the last time you took a break? Probably, it is time to open the application in your browser, wait a few minutes of the Pomodoro working period timer, and check for some kittens.
I just did it and it made me feel really nice and cute:
I'm not your clothes... please have some rest
Let's start with mutations. Open the code in the chapter7/pomodoro folder. Open the mutations.js
file and check what is happening out there. There are four mutations happening: START
, STOP
, PAUSE
, and TOGGLE_SOUND
. Guess which one we will start with. Yes, you are right, we will start with the start
method. Create a vuex
subfolder inside the test/unit/specs
folder and add the mutations.spec.js
file. Let's bootstrap it to be ready for tests:
// mutations.spec.js import Vue from 'vue' import mutations from 'src/vuex/mutations' import * as types from 'src/vuex/mutation_types' describe('mutations', () => { var state beforeEach(() => { state = {} // let's mock Vue noise plugin //to be able to listen on its methods Vue.noise = { start: () => {}, stop: () => {}, pause: () => {} } sinon.spy(Vue.noise, 'start') sinon.spy(Vue.noise, 'pause') sinon.spy(Vue.noise, 'stop') }) afterEach(() => { Vue.noise.start.restore() Vue.noise.pause.restore() Vue.noise.stop.restore() }) describe('START', () => { }) })
Note that I mocked all the methods of the noise generator plugin. This is because in this spec, we don't need to test the plugin's functionality (in fact, we must do it in the scope of the plugin itself before publishing it). For the scope of this test, we should test that the plugin's methods are called when they need to be called.
In order to be able to test the start
method, let's think what should happen. After the start button is clicked, we know that the application's started
, paused
, and stopped
states must gain some specific values (actually, true
, false
, and false
, respectively). We also know the application's interval should be started. We also know that if the Pomodoro's state is working
and if the sound is enabled, the start
method of the noise generator plugin should be called. In fact, this is what our method is actually doing:
[types.START] (state) { state.started = true state.paused = false state.stopped = false state.interval = setInterval(() => tick(state), 1000) if (state.isWorking && state.soundEnabled) { Vue.noise.start() } },
But even if it didn't do all these things and we have written the test to test it, we would immediately understand that something is missing in our code and fix it. Let's then write our test. Let's start by defining the it()
method that tests that all the properties were correctly set. In order to be sure that they are not already set before calling the method, let's also assert that all these properties are not defined at the start of the test:
it('should set all the state properties correctly after start', () => { // ensure that all the properties are undefined // before calling the start method expect(state.started).to.be.undefined expect(state.stopped).to.be.undefined expect(state.paused).to.be.undefined expect(state.interval).to.be.undefined // call the start method mutations[types.START](state) // check that all the properties were correctly set expect(state.started).to.be.true expect(state.paused).to.be.false expect(state.stopped).to.be.false expect(state.interval).not.to.be.undefined })
Let's now check on the Vue.noise.start
method. We know that it should only be called if state.isWorking
is true
and state.soundEnabled
is true
. Let's write a positive test. In this test, we would initialize both Boolean states to true
and check that the noise.start
method is called:
it('should call Vue.noise.start method if both state.isWorking and state.soundEnabled are true', () => { state.isWorking = true state.soundEnabled = true mutations[types.START](state) expect(Vue.noise.start).to.have.been.called })
Let's add two negative tests for each of the states, with isWorking
and soundEnabled
being false
:
it('should not call Vue.noise.start method if state.isWorking is not true', () => { state.isWorking = false state.soundEnabled = true mutations[types.START](state) expect(Vue.noise.start).to.not.have.been.called }) it('should not call Vue.noise.start method if state.soundEnabled is not true', () => { state.isWorking = true state.soundEnabled = false mutations[types.START](state) expect(Vue.noise.start).to.not.have.been.called })
Our start
mutation is nicely tested! Check the final state of the code in the chapter7/pomodoro2 folder. I suggest that you now write the rest of the unit tests not only for the mutations, but also for all the store-related functions that reside in getters and actions. After that, apply the techniques to test Vue components that we just learned and test some of the components of our Pomodoro application.
At this point, we are done with unit testing!
3.141.9.2