我有一个淘汰视图模型,它有一些订阅函数,可以在获取父选择的更改后更新一些默认选择。
但我不确定如何调用该函数并伪造依赖关系以进行测试。
此代码snippit类似于函数,但不是确切的函数。它订阅了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);
});
目前,这会更改选项,但订阅代码似乎根本没有受到影响。
答案 0 :(得分:1)
我确实没有发现您的代码有任何问题,另外您在设置可观察的值后不需要致电subscribe()
;淘汰赛为你做到了。 subscribe方法用于注册处理新值的函数。
重要的是要记住,如果将observable设置为与它已经存在的值相同,订阅将不会被触发。
因此,在您的情况下:如果在SelectedParentOption() === Option1
评论之前Change selection
,则不会重置。如果您想手动触发它,请使用valueHasMutated()
(而不是使用subscribe()
的地方)
查看这些(快速和肮脏)测试。
测试2和3相互矛盾;其中只有一个会通过。他们描述了不同的行为:
我可以想象测试2更好地描述了您正在寻找的内容,但如果您希望测试3通过,您可以将您的observable扩展为始终通知其订阅者。取消注释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>
&#13;
答案 1 :(得分:0)
在更改观察值之前,您应该致电.subscribe()
。它仅在订阅设置后检测更改。试试这个:
// enable subscription
ServerModel.ProductModel.SelectedParentOption.subscribe();
// Change selection
ServerModel.ProductModel.SelectedParentOption(Option1);
// Verify default was selected
expect(ServerModel.ProductModel.SelectedChildOption()).toBe(ExpectedOption);