0

I'm trying to write a test for a ko.computed field that is dependent on two other complex computeds (removed here for demonstration).

function PositionsViewModel(options) {
  var self = this;
  self.computed1 = ko.computed(function() { return 1; });
  self.computed2 = ko.computed(function() { return 2; });
  self.computedIWantToTest = ko.computed(function() { 
    return self.computed1() + self.computed2();
  });
}

In my jasmine test I create an instance of the VM in a beforeEach like so:

this.subject = new PositionsViewModel();

I want to be able to stub computed1 and computed2 so that I may test computedIWantToTest in isolation. So far my attempts to do so have failed.

I've tried stubbing on the vm instance directly. But, it seems that, even though the methods are overwritten the computed caches the function in some way.

iterion
  • 524
  • 4
  • 16
  • You are correct, the `computed` does hold a reference to the observables (including computeds) when it first runs to establish its dependency tracking. You would need to alter the original computeds without creating a new function for them. – Kyeotic Mar 27 '13 at 18:46

1 Answers1

0

One way would be to inject the first two computed functions.

http://jsfiddle.net/kevincollins/RwKAD/

var PositionsViewModel = function (computedService1, computedService2, options) {

  this.defaultComputed1 = ko.computed(function() { return 1; });
  this.defaultComputed2 = ko.computed(function() { return 2; });

  this.computed1 = computedService1 || this.defaultComputed1;
  this.computed2 = computedService2 || this.defaultComputed2;

  var self = this;
  this.computedIWantToTest = ko.computed(function() { 
    return self.computed1() + self.computed2();
  });

};

var vm1 = new PositionsViewModel();
ko.applyBindings(vm1, document.getElementById("o1"));

var ComputedServiceMock1 = ko.computed(function() { return 100; });
var ComputedServiceMock2 = ko.computed(function() { return 200; });       

var vm2 = new PositionsViewModel(ComputedServiceMock1, ComputedServiceMock2);
ko.applyBindings(vm2, document.getElementById("o2"));
Kevin Collins
  • 1,453
  • 1
  • 10
  • 16
  • 1
    It works, but I have to modify my application code to suit testing. I think that's definitely less than ideal. – iterion Mar 30 '13 at 20:15
  • 1
    This is not the right approach. Using dependency injection would become unwieldy on anything large very quickly. What we need is a way to force a computed value to update against the function being spied (and replaced). – genexp May 29 '13 at 16:24