Проверьте, что функция вызывает другую функцию в модуле ES6 с Sinon.js

Я хочу проверить, что функция в модуле ES6 вызывает другую функцию с помощью Sinon.js. Вот основная схема того, что я делаю:

foo.js

export function bar() {
 baz();
}

export function baz() {
 ...
}

test.js

import sinon from 'sinon';
import * as Foo from '.../foo';

describe('bar', function() {
  it('should call baz', function() {
    let spy = sinon.spy(Foo, 'baz');
    spy.callCount.should.eql(0);

    Foo.bar();

    spy.calledOnce.should.eql(true);
  });
}); 

Но шпион не отвечает на вызов baz(). Есть ли другой способ, которым я могу настроить модуль или тест, чтобы позволить синону выбрать это? Моя альтернатива заключается в том, чтобы сделать некоторое базовое утверждение о чем-то, что делает baz, но я, очевидно, не хочу этого делать.

Из того, что я видел в Интернете, мне интересно, возможно ли это с помощью кода, изложенного как есть, или если мне нужно реструктурировать его, чтобы получить то, что я хочу.

Ответ 1

Вы правы, думая, что это невозможно с тем, как модуль в настоящее время структурирован.

Когда код выполняется, ссылка baz внутри function bar разрешена в отношении локальной реализации. Вы не можете изменить это, поскольку вне кода модуля нет доступа к внутренним компонентам.

У вас есть доступ к экспортированным свойствам, но вы не можете их мутировать и поэтому не можете влиять на модуль.

Один из способов изменить это, используя следующий код:

let obj = {};
obj.bar = function () {
 this.baz();
}

obj.baz = function() {
 ...
}

export default obj;

Теперь, если вы переопределите baz в импортированном объекте, вы будете влиять на внутренности bar.

Сказав это, это выглядит довольно неуклюжим. Существуют и другие методы управления поведением, такие как инъекция зависимостей.

Кроме того, вы должны подумать, действительно ли вы заботитесь о том, был ли вызван baz. В стандартном "тестировании черного ящика" вам все равно, как что-то сделано, вам все равно, какие побочные эффекты он генерирует. Для этого проверьте, были ли побочные эффекты, которые вы ожидали, и что ничего больше не было сделано.