Функция-заглушка не может вернуть обещание - PullRequest
0 голосов
/ 02 сентября 2018

Я пытался заглушить функцию стрелки removeUserEntry, но при выполнении acctRmRouter в тесте моя заглушка, похоже, игнорируется. Я должен явно заглушить метод UserModel deleteOne, чтобы успешно пройти тест, мне интересно, почему происходит невежество, спасибо

acctRoute.js

const removeUserEntry = (username) => {
    const condition = {username: username};

    return UserModel.deleteOne(condition)
       .then((res) => {
           if (res.n < 1) {
               throw new Error('User not exists');
           }
           return true;
       }, (err) => {throw err})
       .catch(err => err);
};

const acctRmRouter = function(httpReq, httpRes, next) {
    if (!argValidate(httpReq.body, 'string')) {
        httpRes.locals = {api: { success: false }};
        // return to avoid running downwards
        return next(new Error('bad argument'));
    }

    // perform DB rm user
    return removeUserEntry(httpReq.body).then((res) => {
        if (res === true) {
            httpRes.locals = {api: { success: true }};
            next();
        } else {
            httpRes.locals = {api: { success: false }}
            next(res);
        }
    });
};

acctRoute.spec.js

it('should remove user handler pass success request', async () => {
    shouldDbReset = false;
    const mockRequestURL = "/api/account/rm-user";
    const mockRequest = httpMocks.createRequest({
        method: "POST",
        url: mockRequestURL,
        headers: {
            "Content-Type": "text/plain"
        },
        body: 'validRmUser',
    });
    const mockResponse = httpMocks.createResponse();
    const spyNext = sinon.spy();
    const stubRemoveUserEntry = sinon.stub(accountRouterHelper, 'removeUserEntry'); 

    stubRemoveUserEntry.callsFake(function(){
        return Promise.resolve(true);
    }); // Expecting this function to be stubbed, and always return true

    await accountRouterHelper.acctRmRouter(mockRequest, mockResponse, spyNext); 
    /* But when running the function, it returns error object with "User not exists" 
    which is not what intended */

    const firstCallArgs = spyNext.getCall(0).args[0];

    expect(spyNext.called).to.be.true;
    console.log(`firstCallArgs: ${firstCallArgs}`)
    expect(firstCallArgs instanceof Error).to.be.false;
    expect(spyNext.args[0].length).to.equal(0);
    expect(mockResponse.statusCode).to.equal(200);
    expect(mockResponse.locals.api.success).to.be.true;

    stubRemoveUserEntry.resetHistory();
    stubRemoveUserEntry.restore();
});

Следующее действительно успешно заглушено с похожим шаблоном к removeUserEntry.

acctRoute.js

const createUserEntry = (userData) => {
    const updatedUserData = filterInput(userData);
    const userDoc = new UserModel(updatedUserData);
    return userDoc.save()
    .then((userObj) => userObj._doc
    ,(err) => { throw err;})
    .catch(err => err);
};

const acctCreateRouter = function (httpReq, httpRes, next) {
// do something in mongodb
return createUserEntry(userCondition)
   .then((response) => {
            if (!(response instanceof Error)) {
                httpRes.locals = {api: { success: true}};
                next();
            } else {
                httpRes.locals = {api: { success: false}};
                next(response);
            }
        }, (err) => {
            httpRes.locals = {api: { success: false}};
            next(err);
        })
        .catch((err) => {
            httpRes.locals = {api: { success: false}};
            next(err);
        });     
};

const acctOutputRouter = function(req, res, next) {
    if (res.locals) {
        res.send(res.locals.api);
    } else {next()}
};

acctRoute.spec.js

it("should return and save the success result to response locals for next route", () => {
        shouldDbReset = false;
        const mockResponse = httpMocks.createResponse();
        const stubCreateUserEntry = sinon.stub(accountRouterHelper, 'createUserEntry');
        const mockNext = sinon.spy();

        stubCreateUserEntry.callsFake(function(){
            return Promise.resolve();
        }); // Unlike removeUserEntry, stubbing neatly with desired output
        return accountRouterHelper.acctCreateRouter(mockRequest, mockResponse, mockNext)
        .then(() => {
            expect(mockNext.called).to.be.true;
            expect(mockResponse.locals.api.success).to.be.true;
        })
        .finally(() => {
            mockNext.resetHistory();
            stubCreateUserEntry.restore();
        });
    });

1 Ответ

0 голосов
/ 03 сентября 2018

Issue

sinon.stub(accountRouterHelper, 'removeUserEntry') заменяет модуль экспорта.

acctRmRouter() не вызывает экспорт модуля, он вызывает removeUserEntry() напрямую, поэтому остановка экспорта модуля ничего не делает.

Решение

Refactor acctRmRouter() для вызова экспорта модуля для removeUserEntry().

ES6

// import module into itself
import * as self from './acctRoute';

...

const acctRmRouter = function(httpReq, httpRes, next) {

    ...

    // call the function using the module
    return self.removeUserEntry(httpReq.body).then((res) => {

    ...

Node.js модуль

...

const acctRmRouter = function(httpReq, httpRes, next) {

  ...

  // call the function using module.exports
  return module.exports.removeUserEntry(httpReq.body).then((res) => {

  ...
...