javascript - Jest kullanarak belirli argümanlarla fonksiyonları taklit edebilir miyim?
Bir fonksiyonu Jest ile taklit etmek istiyorum, ama sadece belirli argümanlarla çağrılırsa, örneğin:
function sum(x, y) {
return x + y;
}
// mock sum(1, 1) to return 4
sum(1, 1) // returns 4 (mocked)
sum(1, 2) // returns 3 (not mocked)
Ruby'nin RSpec kütüphanesinde benzer bir özellik uygulanmıştır:
class Math
def self.sum(x, y)
return x + y
end
end
allow(Math).to receive(:sum).with(1, 1).and_return(4)
Math.sum(1, 1) # returns 4 (mocked)
Math.sum(1, 2) # returns 3 (not mocked)
Testlerimde başarmaya çalıştığım şey daha iyi bir ayrıştırma, diyelim ki sum'a bağlı bir fonksiyonu test etmek istiyorum:
function sum2(x) {
return sum(x, 2);
}
// I don't want to depend on the sum implementation in my tests,
// so I would like to mock sum(1, 2) to be "anything I want",
// and so be able to test:
expect(sum2(1)).toBe("anything I want");
// If this test passes, I've the guarantee that sum2(x) is returning
// sum(x, 2), but I don't have to know what sum(x, 2) should return
Bunu şu şekilde bir şey yaparak uygulamanın bir yolu olduğunu biliyorum:
sum = jest.fn(function (x, y) {
if (x === 1 && y === 2) {
return "anything I want";
} else {
return sum(x, y);
}
});
expect(sum2(1)).toBe("anything I want");
Ama bunu basitleştirmek için bazı şeker fonksiyonlarımız olsaydı güzel olurdu.
Mantıklı geliyor mu? Jest'te bu özellikle zaten var mı?
Geri bildiriminiz için teşekkürler.
Cevap #1
Yakın zamanda bir meslektaşımın yazdığı bu kütüphaneyi buldum: jest-when
import { when } from 'jest-when';
const fn = jest.fn();
when(fn).calledWith(1).mockReturnValue('yay!');
const result = fn(1);
expect(result).toEqual('yay!');
İşte kütüphane: https://github.com/timkindberg/jest-when
Cevap #2
Muhtemelen STeve Shary tarafından bahsedilen jest-when en iyi seçenek.
Yeni bir kütüphane yüklemek istemiyorsanız ve orijinal fonksiyonla ilgilenmiyorsanız, işte tek satırlık bir çözüm:
sum.mockImplementation((x, y) => x === 1 && y === 2 && "my-return-value")
Cevap #3
import * as helper from "../helper"; //file where all functions are
jest.spyOn(helper, "function_name").mockImplementation((argument) => {
// This argument is the one passed to the function you are mocking
if (argument === "something") {
return "something"
} else {
return "something else"
}
});
Cevap #4
Ben de argümanlarla birlikte taklit etmenin bir yoluna ihtiyacım olduğunu düşündüm, ama benim için problemi sadece çağrıların sırasını bilerek çözebilirdim.
Jest belgelerinden alınmıştır
const filterTestFn = jest.fn();
// Make the mock return `true` for the first call,
// and `false` for the second call
filterTestFn.mockReturnValueOnce(true).mockReturnValueOnce(false);
Yani yukarıdaki örnekte, eğer ilk geçişte fonksiyonun doğru döndürmesi gerektiğini ve ikinci geçişte yanlış döndürmesi gerektiğini biliyorsanız, hazırsınız demektir!
Cevap #5
Hayır, Jest'te bunu yapmanın bir yolu henüz yok. Bunun için Sinon'un stub'larını kullanabilirsiniz. Belgelerden:
stub.withArgs(arg1[, arg2, ...]);
Yalnızca sağlanan argümanlar için metodu yerine koyar. Bu, aynı çağrıyla casusu (spy) erişebileceğiniz doğrulamalarınızda daha ifadeli olmanıza yardımcı olur. Ayrıca, farklı argümanlara farklı şekilde yanıt verebilen bir stub oluşturmak için de faydalıdır.
"test should stub method differently based on arguments": function () {
var callback = sinon.stub();
callback.withArgs(42).returns(1);
callback.withArgs(1).throws("TypeError");
callback(); // No return value, no exception
callback(42); // Returns 1
callback(1); // Throws TypeError
}
