问题
I've got a JS method in my node.js app that I want to unit test. It makes several calls to a service method, each time passing that service a callback; the callback accumulates the results.
How can I use Jasmine to stub out the service method so that each time the stub is called, it calls the callback with a response determined by the arguments?
This is (like) the method I'm testing:
function methodUnderTest() {
var result = [];
var f = function(response) {result.push(response)};
service_method(arg1, arg2, f);
service_method(other1, other2, f);
// Do something with the results...
}
I want to specify that when service_method is called with arg1 and arg2, the stub will invoke the f callback with a particular response, and when it is called with other1 and other2, it will invoke that same callback with a different particular response.
I'd consider a different framework, too. (I tried Nodeunit, but didn't get it to do what I wanted.)
回答1:
You should be able to use the callFake
spy strategy. In jasmine 2.0 this would look like:
describe('methodUnderTest', function () {
it("collects results from service_method", function() {
window.service_method = jasmine.createSpy('service_method').and.callFake(function(argument1, argument2, callback) {
callback([argument1, argument2]);
});
arg1 = 1, arg2 = 'hi', other1 = 2, other2 = 'bye';
expect(methodUnderTest()).toEqual([[1, 'hi'], [2, 'bye']]);
});
});
Where methodUnderTest
returns the results array.
回答2:
You can't stub it as is, because it's private an internal to the method.
You are testing the wrong thing here. methodUnderTest
should be tested by ensuring that the results are properly handled. Ensuring that service_method
executes it's callback with specific arguments is another test altogether and should be tested independently.
Now the spec for methodUnderTest
can simply be about what happens AFTER that callback. Dont worry if the callbacks work, because you've already tested that elsewhere. Just worry about what the method does with the results of the callback.
Even if service_method
is from a library or vendored code you don't directly control, this still applies. The rule of thumb is to test code YOU yourself write, and trust that other libraries follow the same rule.
回答3:
As I'm not sure you're testing the right thing here, you can use a spy and call spy.argsForCall.
var Service = function () {
};
Service.service_method = function (callback) {
someAsyncCall(callback);
};
function methodUnderTest() {
var result = [];
var f = function(response) {result.push(response)};
Service.service_method(arg1, arg2, f);
Service.service_method(other1, other2, f);
}
in your test:
it('should test something', function () {
spyOn(Service, 'service_method');
methodUnderTest()
var arg1 = Service.argsForCall[0][0];
var arg2 = Service.argsForCall[0][1];
var f = Service.argsForCall[0][2];
if(arg1==condition1 && arg2==condition2){f(response1)}
});
来源:https://stackoverflow.com/questions/8408033/use-jasmine-to-stub-js-callbacks-based-on-argument-values