Jasmine 如何以依赖于闭包变量的任何顺序传递 运行 的规范
Jasmine how pass specs that run in any order that depend on a closure variable
我觉得这应该非常直观...但也许它的工作方式与我在 Rspec 中习惯的想法不同...这是我正在尝试的功能测试:
var finalSet = (function() {
var mount = false
return {
initializePage: function() {
if (mount == false) {
this.mountForm();
mount = true;
}
this.greetCustomer();
},
greetCustomer: function() {
...
},
mountForm: function() {
...
}
}
})();
要点是mount
是一个闭包变量,确保无论initializePage
被调用多少次,mountForm
只被调用一次。
这是我目前的规格:
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)
})
})
})
})
})
如果我单独 运行 规格,它们就会通过。在一起,随机地,只有一个会通过,第一个规范 运行,第二个总是失败。
我知道为什么会这样……但 Jasmine 设置不合适来解决这个问题。
它发生的原因是因为 finalSet
在所有规范中安装一次,这意味着尽管有两个规范,但闭包设置一次。那么会发生什么情况是,如果 "first initialization"
首先测试 运行,对 finalSet.initializePage()
的 beforeEach
调用设置 mount = true
,这第一个规范通过,但是随后,来 "initialize again" test,
mountis still true, it doesn't reset, so neither of the 2
beforeEachcalls to
finalSet.initializePage()will ever call
mountForm`,因为那发生在第一个通过的规范中。因此第二个规范失败了。
另一方面,如果 "initialize again"
运行 首先,对 finalSet.initializePage()
的堆叠 2 beforeEach
调用按预期工作, mountForm
被调用一次,greetCustomer
被调用两次。但是当第一个 "first initialization"
规范被调用时,mount = true
已经被调用了,所以什么也没有被调用。
眼前的问题:有没有办法将闭包重置为第一个 beforeEach
的一部分?
更大的问题:我已经习惯了 Rspec 中的这种嵌套规范,但是......我觉得也许这不是一个人应该在 Jasmine 中测试的方式,所以非常开放更好的测试方法是什么。
谢谢!
您正在尝试跨多个规范测试本质上是全局对象的内容。您将以某种方式修改您的代码以测试您想要的内容。以下是一些想法:
向导出的对象添加一个 reset() 函数,将 mount 变量设置为 false,在您的规范中的 before/afterEach 中调用此函数。这类似于您在每次测试前在 Rails 规范中重置数据库(全局资源)的方式。
让您的代码 return 成为一个函数,而不是立即调用它。您可以将 finalSet 变量重命名为 createFinalSet。这意味着你有一个 finalSet 工厂而不是全局实例或单例;每个测试都会通过 finalSet = createFinalSet()
.
有自己的 finalSet
我觉得这应该非常直观...但也许它的工作方式与我在 Rspec 中习惯的想法不同...这是我正在尝试的功能测试:
var finalSet = (function() {
var mount = false
return {
initializePage: function() {
if (mount == false) {
this.mountForm();
mount = true;
}
this.greetCustomer();
},
greetCustomer: function() {
...
},
mountForm: function() {
...
}
}
})();
要点是mount
是一个闭包变量,确保无论initializePage
被调用多少次,mountForm
只被调用一次。
这是我目前的规格:
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)
})
})
})
})
})
如果我单独 运行 规格,它们就会通过。在一起,随机地,只有一个会通过,第一个规范 运行,第二个总是失败。
我知道为什么会这样……但 Jasmine 设置不合适来解决这个问题。
它发生的原因是因为 finalSet
在所有规范中安装一次,这意味着尽管有两个规范,但闭包设置一次。那么会发生什么情况是,如果 "first initialization"
首先测试 运行,对 finalSet.initializePage()
的 beforeEach
调用设置 mount = true
,这第一个规范通过,但是随后,来 "initialize again" test,
mountis still true, it doesn't reset, so neither of the 2
beforeEachcalls to
finalSet.initializePage()will ever call
mountForm`,因为那发生在第一个通过的规范中。因此第二个规范失败了。
另一方面,如果 "initialize again"
运行 首先,对 finalSet.initializePage()
的堆叠 2 beforeEach
调用按预期工作, mountForm
被调用一次,greetCustomer
被调用两次。但是当第一个 "first initialization"
规范被调用时,mount = true
已经被调用了,所以什么也没有被调用。
眼前的问题:有没有办法将闭包重置为第一个 beforeEach
的一部分?
更大的问题:我已经习惯了 Rspec 中的这种嵌套规范,但是......我觉得也许这不是一个人应该在 Jasmine 中测试的方式,所以非常开放更好的测试方法是什么。
谢谢!
您正在尝试跨多个规范测试本质上是全局对象的内容。您将以某种方式修改您的代码以测试您想要的内容。以下是一些想法:
向导出的对象添加一个 reset() 函数,将 mount 变量设置为 false,在您的规范中的 before/afterEach 中调用此函数。这类似于您在每次测试前在 Rails 规范中重置数据库(全局资源)的方式。
让您的代码 return 成为一个函数,而不是立即调用它。您可以将 finalSet 变量重命名为 createFinalSet。这意味着你有一个 finalSet 工厂而不是全局实例或单例;每个测试都会通过
有自己的 finalSetfinalSet = createFinalSet()
.