Como ter valores de retorno diferentes para várias chamadas em um espião Jasmine

100

Digamos que eu esteja espionando um método como este:

spyOn(util, "foo").andReturn(true);

A função em teste chama util.foovárias vezes.

É possível fazer o espião retornar truena primeira vez que é chamado, mas retornar falsena segunda vez? Ou existe uma maneira diferente de fazer isso?

Mikhail
fonte

Respostas:

163

Você pode usar spy.and.returnValues (como Jasmine 2.4).

por exemplo

describe("A spy, when configured to fake a series of return values", function() {
  beforeEach(function() {
    spyOn(util, "foo").and.returnValues(true, false);
  });

  it("when called multiple times returns the requested values in order", function() {
    expect(util.foo()).toBeTruthy();
    expect(util.foo()).toBeFalsy();
    expect(util.foo()).toBeUndefined();
  });
});

Há uma coisa com a qual você deve ter cuidado, há outra função semelhante ao feitiço returnValuesem s, se você usá-la, o jasmim não irá avisá-lo.

oceano
fonte
20
+1: este é um excelente recurso. Porém, uma palavra de advertência - tome cuidado para não esquecer o 's' em .returnValues- as duas funções são obviamente diferentes, mas passar vários argumentos para .returnValuenão gera um erro. Não quero admitir quanto tempo perdi com aquele personagem.
The DIMM Reaper
@TheDIMMReaper, obrigado. Eu mencionei isso agora.
Ocean
Fazer no beforeEach foi importante para mim, não no teste (it)
Ian
Não há necessidade de se preocupar com erros de ortografia ao usar jasmine no TypeScript, é claro.
Warlike Chimpanzee
27

Para versões mais antigas do Jasmine, você pode usar spy.andCallFakepara Jasmine 1.3 ou spy.and.callFakepara Jasmine 2.0, e você terá que controlar o estado 'chamado', seja por meio de um fechamento simples ou propriedade de objeto, etc.

var alreadyCalled = false;
spyOn(util, "foo").andCallFake(function() {
    if (alreadyCalled) return false;
    alreadyCalled = true;
    return true;
});
voithos
fonte
4
Podemos estender isso para mais de 2 chamadas da seguinte forma: var results = [true, false, "foo"]; var callCount = 0; spyOn (util, "foo"). and.callFake (function () {resultados de retorno [callCount ++];});
Jack
1
Isso pode ser estendido para uma função genérica como: function returnValues ​​() {var args = arguments; var callCount = 0; return function () {return args [callCount ++]; }; }
Tomas Lieberkind
Por que todo esse código quando você pode apenas retornar results.shift ()?
ThaFog
e quando voltarmos observabvles
Lijo
esta opção é mais flexível, pois podemos lançar um erro ou valor de retorno dependendo da ordem da chamada.
0bj3ct