Насмешка над конструктором (или другой функцией) в модуле Node.js за пределами этого модуля - PullRequest
4 голосов
/ 11 ноября 2011

Я использую Jasmine для написания своих тестов, но, думаю, у меня возникла бы эта проблема с любым другим фреймворком для тестирования. Допустим, у нас есть модуль foo с двумя функциями Bar и Baz, которые являются конструкторами (но могут быть просто обычными функциями):

var Bar = exports.Bar = function Bar() {
  this.baz = new Baz();
};

var Baz = exports.Baz = function Baz() {

};

Теперь я хотел бы протестировать Bar, но с поддельной реализацией Baz:

var foo = require('foo');

describe("foo.Bar", function() {
  it("initializes its own Baz", function() {
    spyOn(foo, 'Baz'); // this replaces foo.Baz with a fake implementation
    var bar = new foo.Bar();
    expect(foo.Baz).toHaveBeenCalled();
  });
});

Проблема в том, что этот тест не пройден, потому что Bar создает новый Baz, используя переменную Baz, которую нельзя изменить извне. Единственное, что было заменено с помощью spyOn(), это exports.Baz.

Очевидное решение - написать this.baz = new exports.Baz();, но это немного неловко. Если у меня есть больше функций, которые я хочу использовать внутри моего модуля, мне придется всегда вызывать их все, используя префикс exports.. Есть ли здесь другой подход?

1 Ответ

1 голос
/ 11 ноября 2011

Если вы можете каким-то образом отделить эти два класса, например, позволить другой реализации класса Baz быть переданной в bar, то я думаю, что это лучший путь, и вы должны пойти на это.


Ноесли вы действительно хотите иметь возможность ссылаться на exports.Baz как Baz, то есть один способ, о котором я мог бы подумать, используя with.

Говорят, что используя withэто, как правило, плохая практика, и ее следует избегать, я бы не стал использовать ее в своем собственном коде, но это один из способов ее решения и даже может быть законным использованием , если вы знаете, что вы

Вот так:

with(exports) {

    exports.Bar = function Bar() {
        console.log('this is bar!');
        this.baz = new Baz();
    };

    exports.Baz = function Baz() {
        console.log('original baz!');
    };

}

В другом модуле, если вы измените foo.Baz на что-то другое, Baz внутри foo также найдет его.

Я бы по-прежнему рекомендовал найти способ сделать эти два класса независимыми друг от друга, и тогда вы можете просто дать Bar любую реализацию Baz, которую вы хотите.

...