简体   繁体   中英

First async unit test with Mocha and Sinonjs

I m actually using a micro framework created by my society in which we use Mongoose.

To manage the mongoose object, we created a modelfactory, that returns us a model corresponding to the mongoose name object.

Actually, I m working on an authentication service in which I inject this modelfactory.

I need to unit test it with mocha and sinonjs, but I ma bit lost...

This is my authentication Service method that I want to test :

class AuthenticationService extends Service

  constructor: (modelFactory)->
    super(modelFactory)

    @authorizedClientIds = [
      "123456"
      "toto"
    ]
    @OAuthAccessTokensModel = @modelFactory.getSchema('OAuthAccessTokens')
    @OAuthClientsModel = @modelFactory.getSchema('OAuthClients')
    @OAuthUsersModel = @modelFactory.getSchema('OAuthUsers')
    @OAuthRefreshTokensModel = @modelFactory.getSchema('OAuthRefreshTokens')

  ## Get an access token from the bearer token ##
  getAccessToken: (bearerToken, callback)->
    @OAuthAccessTokensModel.findOne({accessToken: bearerToken}, callback)

module.exports = AuthenticationService

I want to test the getAccessToken method, but I have clearly no idea how to make it work...

I've tried to make something like :

describe("Authentication Service", function () {

    var service;

    before(function () {
        ModelFactory = use('/app/core/config/database/ModelFactory');

        var mock = sinon.mock(ModelFactory.getFactoryInstance([]));
        mock.expects("getSchema").withArgs("user").return({name:'user',getName:function(){}});

        service = new AuthenticationService(mock);
    });

    describe("getAccessToken", function () {
        it('should return-1 when the value is not present', function () {
            var proxy = once(service.getAccessToken());

            mock.verify();
        });
    });
});

How should I do to test it correctly ?

EDIT :

I've tried something, but it seems weird to test because I propose the result to compare, but the result expected too.. So I could never fail the test :x...

describe("Authentication Service", function () {

    var service;

    before(function () {
        ModelFactory = use('/app/core/config/database/ModelFactory');
        var factory = new ModelFactory([]);
        sinon.stub(factory, "getSchema").returns({findOne: sinon.stub().returns()});
        service = new AuthenticationService(factory);
    });

    describe("getAccessToken", function () {
        it('Check if the access token correspond to a database entry', function () {
            stubResult = {token: '123456'};
            service.getAccessToken = sinon.stub().withArgs('1234').returns(undefined);
            assert.equal(service.getAccessToken(), undefined);
        });
    });
});

Some help ?

Thanks for advance

The Unit test should test something that is not mocked/stubbed.

When you have a difficult method handleUnknownToken() this function can call your Authentication Service. The assert() should verify that the handling of the 'undefined' works as expected.
In other words: When you want to unit test f(x) = g()+h() +j(); you can test the correct implementation of g() by stubbing h() and j(), test h() by stubbing g() and j() and test j() by stubbing g() and h().

EDIT: The explanation above is abstract, since I do not know Mongoose/Mocha/Sinonjs. Beneath I'll try to focus on the case described.

When your service getAccessToken() is completely stubbed, the next tests will succeed when your stub definition is correct:

testUnknown() {
   constant UKNOWN_ITEM='1234';
   assert.equal(service.getAccessToken(UNKNOWN_ITEM), undefined);
}

testTimeout() {
   constant DIFFICULT_ITEM='1235';
   assert.equal(service.getAccessToken(DIFFICULT_ITEM), STATUS_TIMEOUT);
}


testRevoked() {
   constant REVOKED_ITEM='1236';
   assert.equal(service.getAccessToken(REVOKED_ITEM), STATUS_DENIED);
}

testActive() {
   constant ACTIVE_ITEM='1237';
   assert.equal(service.getAccessToken(ACTIVE_ITEM), STATUS_OK);
}

Your test must include some logic you don't stub. Waht is the code around calling getAccessToken()? Something like a function isTokenOK(), that will look at the status and retry 5 times after a timeout? With the stubs implemented for the above test you can test the boolean function isTokenOK() with

testUnknown() {
   assertFalse(isTokenOK(UNKNOWN_ITEM));
}

testTimeout() {
   assertFalse(isTokenOK(DIFFICULT_ITEM));
}


testRevoked() {
   assertFalse(isTokenOK(REVOKED_ITEM));
}

testActive() {
   assertTrue(isTokenOK(ACTIVE_ITEM));
}

And now, when somebody changes the implementation of isTokenOK(), your unit test can fail. When the unit test is failing, you must look who is right. Maybe a token that has been revoked can be used for authentication the first 10 minutes after revocation and isTokenOK(REVOKED_ITEM) should be true. Oh well, than you must add a new test for REVOKED_ITEM_YESTERDAY.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM