У нас есть то, что мы называем CORShttpService, который, по сути, является оберткой вокруг службы $http, но содержит некоторые необходимые нам функции CORS. Сейчас я пишу несколько тестов для службы, в которую вставлен CORShttpService. Этот сервис имеет такой код:

CORShttpService({method: requestMethod, url: getUrl(path), data: data}).
    success(function(data, status, headers) {
        //do success stuff
    }).
    error(function(data, status, headers) {
       //do error stuff
    });

Я хочу посмеяться над вызовом CORShttpService, но я не уверен, как это сделать. Я использую Jasmine, и для его spyOn функции требуется объект, чтобы высмеивать функцию над объектом. Мой CORShttpService не привязан ни к какому объекту, поэтому я не знаю, как его насмехаться. Да, я мог бы использовать $httpBackend для насмешки над запросами, которые в конечном итоге были заданы в CORShttpService, но я не хочу, чтобы это входило в этот сервис. Я хочу изолировать модульный тест и просто высмеивать внешние вызовы. Есть ли способ, которым я могу издеваться над этим сервисом, который является просто функцией?

2
dnc253 26 Янв 2013 в 03:23

2 ответа

Лучший ответ

Как я уже думал об этом, служба $httpBackend предоставляет множество функциональных возможностей для запросов на тестирование. Поскольку мой CORShttpService по сути является оберткой вокруг $http, я решил, что, возможно, смогу получить максимальную отдачу от своего бакса, если бы я сделал простую реализацию CORShttpService простой {{X4} } реализация. Используя эту документацию, чтобы помочь мне, в моей спецификации есть следующее:

beforeEach(module(function($provide) {
    $provide.provider('CORShttpService', function() {
        this.$get = function($http) {
            return $http;
        };
    });
}));

Итак, любой из моих сервисов, которым требуется инъекция CORShttpService, теперь будет просто внедряться $http и, таким образом, позволит мне использовать все функциональные возможности $httpBackend, не обращая внимания на дополнительные функциональные возможности, обнаруженные в сам CORShttpService.

Это работает для моего конкретного случая, но что касается общего решения для сервисов мошенничества, которые являются просто функцией, то же самое можно сделать с jasmine.createSpy, как упомянуто в ответе zbynour. Что-то вроде:

beforeEach(module(function($provide) {
    $provide.provider('MyService', function() {
        this.$get = function() {
            return jasmine.createSpy("myService");
        };
    });
}));
7
dnc253 28 Янв 2013 в 19:08

Да, как вы написали, spyOn может заглушить функцию, но она должна быть свойством уже существующего объекта. Я также согласен, что лучше изолировать устройство. :)

Что вам нужно, это jasmine.createSpy. Таким образом, вы можете создать голого шпиона и определить его поведение как обычно (используя andReturn, andCallFake и т. Д.).

Я думаю, что-то вроде облака ниже (также с jasmine.createSpyObj) облаком будет тем, что вы хотите:

it ('should do sth', function() {

    var res = jasmine.createSpyObj('res', [ 'success', 'error' ]);
    res.success.andReturn(res);
    res.error.andReturn(res);
    var corsHttpService = jasmine.createSpy().andReturn(res);

    // call the service using corsHttpService
    anotherService(corsHttpService);

    // assert
    expect(corsHttpService).toHaveBeenCalledWith({
        method: requestMethod, 
        url: url,
        data: data});
    expect(res.success).toHaveBeenCalledWith(jasmine.any(Function));
    expect(res.error).toHaveBeenCalledWith(jasmine.any(Function));
});

Если вы хотите пойти дальше, а не просто

res.success.andReturn(res);

Вы можете сохранить обратный вызов, переданный в

var succCallback;
res.success.andCallFake(function(callback) {
        succCallback = callback;
        return res;
    });

И позже в спецификации вы можете вызвать обратный вызов, чтобы эмулировать результат успеха из corsHttpService:

succCallback('a-data', 'a-status', 'a-header');

Тогда можно протестировать «материал успеха» протестированного сервиса ...

2
zbynour 26 Янв 2013 в 12:33