Единственное решение, которое я могу придумать, что не предполагает изменение кода ViewModel
, это заглушка ko.computed
сначала ...
В приведенном ниже примере я заменяю ko.computed
на расширенную версию. Расширение предоставляет свойство .stub
, которое позволяет вам написать пользовательскую функцию. Когда эта функция установлена, вычисляемая будет переоценена с использованием предоставленной логики.
В вашем тестовом файле вам понадобится заменить глобальную ссылку на ko.computed
в коде подготовки, до создания экземпляра экземпляра ViewModel.
// Extender that allows us to change a computed's main value getter
// method *after* creation
ko.extenders.canBeStubbed = (target, value) => {
if (!value) return target;
const stub = ko.observable(null);
const comp = ko.pureComputed(() => {
const fn = stub();
return fn ? fn() : target();
});
comp.stub = stub;
return comp;
}
// Mess with the default to ensure we always extend
const { computed } = ko;
ko.computed = (...args) =>
computed(...args).extend({ canBeStubbed: true });
// Create the view model with changed computed refs
const ViewModel = function() {
this.otherComputed = ko.computed(() => true);
this.computedUnderTest = ko.computed(() => this.otherComputed());
};
const vm = new ViewModel();
function expect(expected) {
console.log("Test succeeded:", vm.computedUnderTest() === expected);
}
expect(true);
// Replace the `otherComputed`'s code by another function
vm.otherComputed.stub(() => false);
expect(false);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
В моих собственных проектах я склонен использовать совершенно другой подход для тестирования своих вычислений, который фокусируется на отделении логики от зависимостей. Дайте мне знать, если приведенный выше пример не работает для вас. (Я не собираюсь писать другой ответ, если это уже удовлетворяет ваши потребности)