I feel like this should be really intuitive... but maybe it doesn't work the same way I'm used to thinking of it in Rspec... Here's the function I'm trying to test:
var finalSet = (function() {
var mount = false
return {
initializePage: function() {
if (mount == false) {
this.mountForm();
mount = true;
}
this.greetCustomer();
},
greetCustomer: function() {
...
},
mountForm: function() {
...
}
}
})();
The gist is that mount
is a closure variable that ensures that regardless how many times initializePage
is called, mountForm
is only called once.
This is my current spec:
describe("finalSet", function() {
describe("initializePage", function() {
beforeEach(function() {
spyOn(finalSet, "mountForm")
spyOn(finalSet, "greetCustomer")
})
describe("first initialization", function() {
beforeEach(function() {
finalSet.initializePage();
})
it("calls both methods", function() {
expect(finalSet.mountForm).toHaveBeenCalled()
expect(finalSet.greetCustomer).toHaveBeenCalled()
})
describe("initialize again", function() {
beforeEach(function() {
finalSet.initializePage();
})
it("repeat calls only greetCustomer", function() {
expect(finalSet.mountForm.calls.count()).toEqual(1)
expect(finalSet.greetCustomer.calls.count()).toEqual(2)
})
})
})
})
})
If I run the specs individually, they pass. Together, and at random, only 1 will pass, the first spec that is run, the second will always fail.
I know why this is happening... but not the appropriate Jasmine set up to fix this issue.
The reason it's happening is because finalSet
mounts once across all specs, meaning the closure is set once despite there being two specs. So what happens is that if the "first initialization"
test runs first, the beforeEach
call to finalSet.initializePage()
sets the mount = true
, this first spec passes, but then, come the "initialize again" test,
mount is still true, it doesn't reset, so neither of the 2
beforeEach calls to
finalSet.initializePage() will ever call
mountForm`, since that happened in the first spec that passed. Hence the second spec fails.
On the other hand, if "initialize again"
runs first, the stacked 2 beforeEach
calls to finalSet.initializePage()
work as expected, mountForm
is called once, greetCustomer
is called twice. But then when the first "first initialization"
spec is called, mount = true
already, so nothing gets called.
The immediate question: is there a way to reset the closure as part of the first beforeEach
?
The larger question: I'm used to this kind of nested speccing from Rspec, but... I'm feeling like maybe this is NOT how one should test in Jasmine, so very open to what a better way of testing this would be is.
Thanks!
You're trying to test what's essentially a global object across multiple specs. You'll modify your code in some way to test what you want. Here are some ideas:
Add a reset() function to the exported object that sets the mount variable to false, Call this function in a before/afterEach in your specs. This is similar to how you might reset a database (a global resource) in a Rails spec before every test.
Have your code return a function instead of immediately invoking it. You might rename the finalSet variable as createFinalSet. This means you have a finalSet factory instead of a global instance or singleton; each test would have its own finalSet via finalSet = createFinalSet()
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.