2015-07-24 4 views
4

Я тестирую устройство с угловым контроллером, который использует фабрику Rails Resource для обработки данных модели GET и POSTing от и до приложения Rails. POSTing выполняется с помощью метода на модели, например. (С моделью $scope.resource):Состояние испытания объекта Jasmine по методу Ajax spy call

$scope.resource.update().then(successHandler, failureHandler); 

У меня есть шпион по этому методу, чтобы погасить окурок Аякс вызовов, так что я могу модульное тестирование контроллер:

resUpdateSpy = spyOn($scope.resource, 'update').and.callFake(function() { 
    return {then: function(success, failure){ success(resUpdateResponse); }}; 
}); 

В одном из моих методов контроллера, я ожидайте, что ресурс будет POSTED с определенными данными (в частности, данные Stripe). Данные будут переопределены после POST в том же методе, поэтому я не смогу проверить состояние модели после этого. В идеале я хотел бы что-то вроде:

expect($scope.resource.update).toHaveBeenCalled().whileValueOf($scope.resource.stripeKey).isEqualTo('tok123'); 

Очевидно, что этот метод не существует в ванильном жасмине. Есть ли способ в Жасмин (или ваниль или через сторонний проект) проверить состояние значения при вызове данного шпиона? или есть ли другой способ проверить эту ситуацию - в частности, состояние модели до ее POST-данных - что мне не хватает?

Я запускаю Jasmine 2.2.0 с Teaspoon 1.0.2 на Угловом 1.3.14 приложении.

+0

Просто поясните: хотите ли вы проверить состояние модели еще до того, как вы ее опубликуете (прежде чем вы вызовете '$ scope.resource.update()') ** или **, когда ответ от POST пришел, и вы хотите проверить его, прежде чем он будет изменен в обработчике 'then()'? –

+0

@MichaelRadionov Я хочу проверить состояние модели перед POST. Поскольку это единичный тест, я завершаю ответ, поэтому нет смысла тестировать его. – eirikir

ответ

1

Как у вас уже есть шпион вперед вызова фальшивой функции, есть что поддельные функции сохраняют значение интереса для вас:

var scopeResourceStripeKeyDuringSpyCall = '(spy not called, yet)'; 
resUpdateSpy = spyOn($scope.resource, 'update').and.callFake(function() { 
    scopeResourceStripeKeyDuringSpyCall = $scope.resource.stripeKey; 
    return {then: function(success, failure){ success(resUpdateResponse); }}; 
}); 

Затем просто проверить хранимое одноразовое значение в ваше утверждение:

expect(scopeResourceStripeKeyDuringSpyCall).toEqual('tok123'); 

(в зависимости от того, находятся в той же области установки шпиона и утверждение, переменная для хранения значения, возможно, придется быть менее локальными.)

3

вы можете добавить свой собственное jasime matchers, то, что вам нужно будет

jasmine.Matchers.prototype.toBeResolvedWith = function() { 
    var done, expectedArgs; 
    expectedArgs = jasmine.util.argsToArray(arguments); 
    if (!this.actual.done) { 
    throw new Error('Expected a promise, but got ' + jasmine.pp(this.actual) + '.'); 
    } 
    done = jasmine.createSpy('done'); 
    this.actual.done(done); 
    this.message = function() { 
    if (done.callCount === 0) { 
     return ["Expected spy " + done.identity + " to have been resolved with " + jasmine.pp(expectedArgs) + " but it was never resolved.", "Expected spy " + done.identity + " not to have been resolved with " + jasmine.pp(expectedArgs) + " but it was."]; 
    } else { 
     return ["Expected spy " + done.identity + " to have been resolved with " + jasmine.pp(expectedArgs) + " but was resolved with " + jasmine.pp(done.argsForCall), "Expected spy " + done.identity + " not to have been resolved with " + jasmine.pp(expectedArgs) + " but was resolved with " + jasmine.pp(done.argsForCall)]; 
    } 
    }; 
    return this.env.contains_(done.argsForCall, expectedArgs); 
}; 

более доступно здесь https://gist.github.com/gr2m/2191748

обновленных после комментария:

в основном жасмин поддерживает пользовательскую matchers. некоторые из встроенных матчи - toBe, toEqual и т. д. Вы можете добавить свой собственный custom matcher, чтобы проверить обещание.

var customMatchers = { 

toHaveBeenResolved: function(util, customEqualityTesters) { 
    return { 
    compare: function(actual, expected) { 
     var result = {}; 
     // do you comparison logic here 
     result.pass = true/false; 
     result.message = 'some message about test result'; 
     return result; 
    } 
} 

this.actual это обещание, и вы можете решить ее как этот

result = {}; 
promise.then(function(value){ 
    result.value = value; 
    result.status = 'Resolved'; 
}, function(value){ 
    result.value = value; 
    result.status = 'Rejected'; 
}); 

когда вы объявили вас обычай согласовани использовать его в вас тесте в beforeEach обратного вызова.

beforeEach(function() { 
    jasmine.addMatchers(customMatchers); 
}); 
+0

Спасибо, это отлично выглядит, но не могли бы вы добавить дополнительные объяснения? Я не уверен, что именно, это тестирование. В частности, «done.argsForCall» представляет модель перед POST (последняя - это то, что я пытаюсь проверить)? Кроме того, я считаю, что это использует синтаксис для Jasmine 1, но я на Jasmine 2.2.0 (извините за то, что вы не включили это в оригинальный вопрос, с тех пор я обновил), и это вызывает ошибку, которая 'jasmine.Matchers' не определена , – eirikir

+0

обновленный ответ. – atinder

+0

@atiender Это имеет смысл на общем уровне, но я также пытаюсь понять, в частности, как работает ваш 'toBeResolvedWith', чтобы я мог адаптировать его к моему проекту. Вызывается ли он как «ожидать (myPromise) .toBeResolvedWith (someResult)»? Будет ли это «фактическим» обещание или представление обещания или что-то еще? Что такое 'this.actual.done'? Что такое 'done.identity'? Что возвращается? Извините, я знаю, что у вас много вопросов; Я обычно не разработчик JS, поэтому я не так хорошо знаком с семантикой Jasmine. – eirikir

Смежные вопросы