Unit tests on methods/publication that requires au

2019-07-29 14:41发布

I'm writing unit test for my Meteor 1.4.2 application, where few of my methods requires authentication before processing. How should I test these methods?

So far, I've written a test with practicalmeteor:mocha to create a new user and login with that user.

describe('login method', function () {
let logingKey;
beforeEach(function () {
  Meteor.users.remove({});
  const createUser = Meteor.server.method_handlers['registerUser'];
  let params = {
    username: 'testUsername'
  }
  res = createUser.apply({}, [params]);
  logingKey = res.key;
});

it('can provide authentication', function () {
  const loginUser = Meteor.server.method_handlers['login'];
  let params = {
    key: logingKey
  }
  console.log(params);
  loginUser.apply({}, [params]);
});

I've written a custom login handler to login with the generated key which works fine with application, but in test results I'm getting following error.

Error: Cannot read property 'id' of undefined
at AccountsServer.Ap._setLoginToken (packages/accounts-base/accounts_server.js:889:35)
at packages/accounts-base/accounts_server.js:288:10
at Object.Meteor._noYieldsAllowed (packages/meteor.js:671:12)
at AccountsServer.Ap._loginUser (packages/accounts-base/accounts_server.js:287:10)
at AccountsServer.Ap._attemptLogin (packages/accounts-base/accounts_server.js:349:12)
at Object.methods.login (packages/accounts-base/accounts_server.js:533:21)
at Object.methodMap.(anonymous function) (packages/meteorhacks_kadira.js:2731:30)
at Test.<anonymous> (imports/api/methods/loginUser.tests.js:30:17)
at run (packages/practicalmeteor:mocha-core/server.js:34:29)
at Context.wrappedFunction (packages/practicalmeteor:mocha-core/server.js:63:33)

What could be wrong here? any suggestions are welcome, thanks in advance.

Original post on meteor forum

UPDATE

Ok! here is my confustion, Let say I've a write a unit test for this method, How should I verify or get the userId here.

Meteor.methods({
  userStatus:function(update){
      check(update, {online: String})
      if (! this.userId) {
          throw new Meteor.Error('error-not-authorized','User need to login', {method: "userStatus"})
      }
      try {
        Meteor.users.update(Meteor.userId(),{$set: {'status.online': !!parseInt(update.online)}})
      } catch (e) {
        console.error("Error",e);
      }
  }
});

1条回答
姐就是有狂的资本
2楼-- · 2019-07-29 15:13

You are directly invoking a method handler without an appropriate context (which should be a Method Invocation object, while you provide an empty object). The login method handler attempts to get the connection id and fails to do so.

If you want to test the integration of your package with the accounts-base package (and basically you do, as you are calling some of its code), you can create a connection and call the method with that connection.

let connection = DDP.connect(Meteor.absoluteUrl());
// prepare the login data
const params = {/*...*/};
connection.call('login', params);
// test post conditions
connection.disconnect();

Edit (following question edit):

The answer remains pretty much the same. Once you have called the login method and logged in the user, the connection state on the server should include the logged-in user's id. Now you can call the methods that require the user to be logged in.

Note that you should probably use this.userId on all occasions (and not Meteor.userId()).

查看更多
登录 后发表回答