javascript - 如何使用 Jasmine 对 Knockout.js 订阅功能进行单元测试?

标签 javascript c# unit-testing knockout.js jasmine

我有一个 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/

相关文章:

javascript - string.prototype.search ('$' ) 在每个字符串上返回正 int

r - 在 Travis CI 上为 R 包指定 valgrind 选项

javascript - 获取当前工作目录名称而不是 Node.js 中的路径

c# - Math.Cound标签在C#中

c# - 如何在不使用 InvalidPluginExecutionException 的情况下通过插件向用户发送警报?

c# - 插入 ASPNET CORE 时出现错误重复信息

PHPUnit 和命名空间 - 仍在调用模拟方法

python - python mock __init__() 返回伪类的正确方法

html文档中的javascript和css,最佳实践?

javascript - 使用 JQuery 和 Javascript 在 Chrome 扩展程序中未触发事件