Шпионить за методом объекта, созданного динамически во время выполнения теста

Мне нужно шпионить за методом объекта, созданного динамически внутри другого метода

Поэтому учтите следующее:

public doStuff = () => {
    const myThing = new MyThing();
    myThing.doSomethingElse().then((data) => {
        //do more stuff here...
    })
}

Поэтому я хочу шпионить за экземпляром MyThing и вызовом doSomethingElse().

Я нашел решение здесь, которые используют prototype объекта, что я и пытался сделать так

spyOn(MyThing.prototype, 'doSomethingElse').and.returnValue(Promise.resolve({foo: 'bar'}));

Но это не работает, после того как я вызываю doStuff() в своих тестах, я получаю сообщение об ошибке:

Ошибка: метод doSomethingElse() не существует

Но я знаю, что этот метод хорош, так как он работает, как и ожидалось, локально.

Я не уверен, как поступить, может ли кто-нибудь помочь? Спасибо


person mindparse    schedule 11.07.2019    source источник
comment
Можете ли вы показать больше вашего теста? imports и инициализация переменных. Кроме того, вы можете показать содержимое MyThing?   -  person Castro Roy    schedule 11.07.2019
comment
Ваша основная проблема заключается в сильно связанном дизайне, у doStuff есть жесткая зависимость от MyThing, это не легко тестируемый дизайн. Ваши объекты должны быть слабо связаны с зависимостями, введенными через параметры. public doStuff = (myThing), а затем myThing можно внедрить во время выполнения, включая тесты.   -  person Adrian Brand    schedule 12.07.2019


Ответы (2)


Возможно, вы что-то упустили в своем тесте. Это простой тест, и вы можете видеть, что он работает так, как вы ожидали.

require("jasmine");

class MyThing {
  async doSomethingElse() {
    return { bar: "foo" };
  }
}

class Stuff {
  doStuff() {
    const myThing = new MyThing();
    myThing.doSomethingElse().then(data => {
      console.log(data);
    });
  }
}

describe("doSomethingElse", () => {
  it("toHaveBeenCalled", () => {
    spyOn(MyThing.prototype, "doSomethingElse").and.returnValue(
      Promise.resolve({ foo: "bar123" })
    );

    const stuff = new Stuff();
    stuff.doStuff();

    expect(MyThing.prototype.doSomethingElse).toHaveBeenCalled();
  });
});

Ключевым моментом является использование spyOn перед созданием экземпляра класса, содержащего функцию doStuff. Если мы переместим const stuff = new Stuff(); выше spyOn, это не удастся.

Надеюсь, поможет

person Castro Roy    schedule 11.07.2019

Вы можете создать объект-шпион с фиктивным методом, передав объект, имена свойств которого представляют возвращаемые данные для методов.

describe('test', () => {
  let mock;
  beforeEach(() => {
    mock = jasmine.createSpyObj('mock', {
      doSomethingElse: Promise.resolve({foo: 'bar'})
    });
  });
  
  it('call mock', async () => {
    const result = await mock.doSomethingElse();
    expect(result.foo).toEqual('bar');
  });
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.4.0/jasmine.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.4.0/jasmine.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.4.0/jasmine-html.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jasmine/3.4.0/boot.js"></script>

person Adrian Brand    schedule 11.07.2019