首次使用 Mocha 和 Sinonjs 进行异步单元测试

First async unit test with Mocha and Sinonjs

我实际上使用的是我的社会创建的微框架,我们在其中使用了 Mongoose。

为了管理 mongoose 对象,我们创建了一个模型工厂,returns 我们使用与 mongoose 名称对象对应的模型。

实际上,我正在开发一个身份验证服务,我在其中注入了这个 modelfactory。

我需要用 mocha 和 sinonjs 对其进行单元测试,但我有点迷茫...

这是我要测试的身份验证服务方法:

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

我想测试 getAccessToken 方法,但我显然不知道如何让它工作...

我试过做类似的东西:

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();
        });
    });
});

我应该怎么做才能正确测试它?

编辑:

我已经尝试过一些东西,但测试起来似乎很奇怪,因为我提出要比较的结果,但结果也是预期的..所以我永远不会失败测试: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);
        });
    });
});

有帮助吗?

感谢提前

单元测试应该测试不属于 mocked/stubbed 的东西。

当你有一个困难的方法 handleUnknownToken() 这个函数可以调用你的身份验证服务。 assert() 应该验证 'undefined' 的处理是否按预期工作。
换句话说:当你想进行单元测试时 f(x) = g()+h() +j();您可以通过打桩 h() 和 j() 来测试 g() 的正确实现,通过打桩 g() 和 j() 来测试 h() 并通过打桩 g() 和 h() 来测试 j()。

编辑:上面的解释是抽象的,因为我不知道Mongoose/Mocha/Sinonjs。下面我将尝试着重描述所描述的案例。

当您的服务 getAccessToken() 完全存根时,接下来的测试 当您的存根定义正确时将会成功:

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);
}

您的测试必须包含一些您不存根的逻辑。 调用 getAccessToken() 的代码是什么?类似函数的东西 isTokenOK(),那个会看状态,超时后重试5次? 使用为上述测试实现的存根,您可以使用

测试布尔函数 isTokenOK()
testUnknown() {
   assertFalse(isTokenOK(UNKNOWN_ITEM));
}

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


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

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

现在,当有人更改 isTokenOK() 的实现时,您的单元测试可能会失败。当单元测试失败时,你必须看看谁是对的。 也许已被撤销的令牌可以在撤销后的前 10 分钟内用于身份验证,并且 isTokenOK(REVOKED_ITEM) 应该为真。 哦,好吧,你必须为 REVOKED_ITEM_YESTERDAY 添加一个新测试。