Метеор / Жасмин / Скорость: как проверить серверный метод, требующий входа в систему пользователя?

Используя скорость / жасмин, я немного застрял в том, как я должен протестировать серверный метод, требующий, чтобы в данный момент был вошедший в систему пользователь. Есть ли способ заставить Метеор думать, что пользователь вошел в систему через заглушку / фейк?

myServerSideModel.doThisServerSideThing = function(){
    var user = Meteor.user();
    if(!user) throw new Meteor.Error('403', 'not-autorized');
}

Jasmine.onTest(function () {
    describe("doThisServerSideThing", function(){
        it('should only work if user is logged in', function(){
            // this only works on the client :(
            Meteor.loginWithPassword('user','pwd', function(err){
                expect(err).toBeUndefined();

            });
        });
    });
});

4 ответа

Решение

Что вы можете сделать, это добавить пользователей только в ваш набор тестов. Вы можете сделать это, заполнив этих пользователей в тестовом сценарии на стороне сервера:

Что-то вроде:

Jasmine.onTest(function () {
  Meteor.startup(function() {
    if (!Meteor.users.findOne({username:'test-user'})) {
       Accounts.createUser
          username: 'test-user'
  ... etc

Тогда хорошей стратегией может быть использование beforeAll в вашем тесте для входа (это на стороне клиента):

Jasmine.onTest(function() {
  beforeAll(function(done) {
    Meteor.loginWithPassword('test-user','pwd', done);
  }
}

Предполагается, что ваш тест еще не авторизован. Вы можете сделать это более модным, проверив Meteor.user() и правильно выйдя из afterAllи т. д. Обратите внимание, как вы можете легко передать done обратный звонок ко многим из Accounts функции.

По сути, вам не нужно издеваться над пользователем. Просто убедитесь, что в базе данных Velocity/Jasmine есть нужные пользователи с правильными ролями.

Допустим, у вас есть такой метод на стороне сервера:

Meteor.methods({
    serverMethod: function(){
        // check if user logged in
        if(!this.userId) throw new Meteor.Error('not-authenticated', 'You must be logged in to do this!')

       // more stuff if user is logged in... 
       // ....
       return 'some result';
    }
});

Вам не нужно создавать Meteor.loginWithPassword перед выполнением метода. Все, что вам нужно сделать, это заглушить this.userId изменяя this контекст вызова функции метода.

Все определенные метеорные методы доступны на Meteor.methodMap объект. Так что просто вызовите функцию с другим this контекст

describe('Method: serverMethod', function(){
    it('should error if not authenticated', function(){
         var thisContext = {userId: null};
         expect(Meteor.methodMap.serverMethod.call(thisContext).toThrow();
    });

    it('should return a result if authenticated', function(){
         var thisContext = {userId: 1};
         var result = Meteor.methodMap.serverMethod.call(thisContext);
         expect(result).toEqual('some result');
    });

});

РЕДАКТИРОВАТЬ: Это решение было протестировано только на Meteor <= 1.0.x

Я думаю что Meteor.server.method_handlers["nameOfMyMethod"] позволяет вызвать / применить метод Метеор и снабжение this как первый параметр хотя бы в текущей версии (1.3.3)

this.userId = userId;
Meteor.server.method_handlers["cart/addToCart"].apply(this, arguments);

Что вы тестируете и почему требуется, чтобы пользователь вошел в систему? Большинству методов, которые у меня есть, нужен пользовательский объект, в который я передаю пользовательский объект. Это позволяет мне звонить из теста без фактического входа в систему. Поэтому при фактическом выполнении кода я бы прошел...

var r = myMethod(Meteor.user());

но при запуске из теста я бы назвал как...

it('should be truthy', function () {
  var r = myMethod({_id: '1', username: 'testUser', ...});
  expect(r).toBeTruthy();
});
Другие вопросы по тегам