我有一个 knockout View 模型,它有一些订阅函数,这些函数在获取对父选择的更改后更新一些默认选择。
但我不确定如何调用该函数并伪造依赖项以对其进行测试。
此代码片段与该函数类似,但不完全相同。它订阅了 SelectedParentOption observable,当它更改为检查可用内容并选择新值时。
//When selection changes select default for remaining selection
self.ServerModel.ProductModel.SelectedParentOption.subscribe(function () {
// Loop through options returned by function checking for correct key
self.availableOptions().forEach(function (option) {
if (option.Key == 1)
// Assign default selection
self.ServerModel.ProductModel.SelectedChildOption(option);
}
});
这是 Jasmine 单元测试
it("Selection set to default after change", function () {
// Spy on available options to dictate what's available
spyOn(testModel, 'availableOptions').and.returnValue(TestOptions);
// Change selection
ServerModel.ProductModel.SelectedParentOption(Option1);
// Call function
ServerModel.ProductModel.SelectedParentOption.subscribe();
// Verify default was selected
expect(ServerModel.ProductModel.SelectedChildOption()).toBe(ExpectedOption);
});
目前,这改变了选项,但订阅代码似乎根本没有受到影响。
最佳答案
我真的没有发现你的代码有什么问题,除了你不需要在设置可观察值的值后调用 subscribe()
; knockout 会为你做到这一点。 subscribe 方法用于注册一个处理新值的函数。
但是请务必记住,如果可观察值设置为与其已持有的值相同的值,则不会触发订阅。
因此,在您的情况下:如果 SelectedParentOption() === Option1
在您的 Change choice
注释之前,则不会发生重置。如果您想手动触发它,请使用 valueHasMutated()
(而不是使用 subscribe()
)
看看这些(快速而肮脏的)测试。
测试 2 和测试 3 相互矛盾;只有其中 1 个会通过。他们描述了不同的行为:
- 2:仅当父选择实际更改时才重置
- 3:当有人设置父选择时始终重置,即使它与之前的值相同
我可以想象测试 2 更好地描述了您正在寻找的内容,但如果您希望测试 3 通过,您可以将您的可观察对象扩展为始终通知其订阅者。取消 ViewModel 中的注释以查看差异。
function ViewModel() {
this.selectedParent = ko.observable(0)/*.extend({notify: 'always'})*/;
this.children = [{ key: 0 }, { key: 1}, { key: 2 }];
this.selectedChild = ko.observable(null);
this.selectedParent.subscribe(function() {
this.selectedChild(this.children.find(function(child) {
return child.key === 1;
}));
}, this)
}
describe('Subscription test', function() {
var vm;
beforeEach(function() {
vm = new ViewModel();
});
it("should reset child selection to child 1 when parent changes", function() {
expect(vm.selectedChild()).toBe(null);
vm.selectedParent(1);
expect(vm.selectedChild().key).toBe(1);
});
it("should not reset child when re-setting the same parent selection", function() {
vm.selectedParent(1);
vm.selectedChild(vm.children[2]);
expect(vm.selectedChild().key).toBe(2);
// Same primitive, won't trigger the subscription
vm.selectedParent(1);
expect(vm.selectedChild().key).toBe(2);
});
// To fix this test, uncomment .extend in selectedParent
it("should always reset child when re-setting the same parent selection", function() {
vm.selectedParent(1);
vm.selectedChild(vm.children[2]);
expect(vm.selectedChild().key).toBe(2);
vm.selectedParent(1);
expect(vm.selectedChild().key).toBe(1);
});
it("should initialize without a selection", function() {
expect(vm.selectedChild()).toBe(null);
});
it("should set selections", function() {
vm.selectedChild(vm.children[2]);
expect(vm.selectedChild().key).toBe(2);
});
});
<script src="http://searls.github.io/jasmine-all/jasmine-all-min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
关于javascript - 如何使用 Jasmine 对 Knockout.js 订阅功能进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40087139/