Тестирование Mocha / Chia не ожидает завершения цепочек методов перед тем, как пройти / не пройти тест - PullRequest
0 голосов
/ 23 февраля 2019

Так что я уже некоторое время работаю над этим проектом, но я так и не смог понять, как заставить мое тестирование работать.Я пытался протестировать свой API различными способами, однако каждый раз, когда я менял что-то, казалось, только возникало больше проблем.На данный момент я в замешательстве, мне нужны свежие глаза, чтобы проверить это.

К вашему сведению, API на самом деле работает нормально, я могу назвать все свои маршруты и получить правильные результаты без проблем, я былиспользуя httpie для сортировки «тестов» без написания каких-либо тестов.

В любом случае, вот часть кода, который я выполнял:

const chai = require('chai');
const expect = chai.expect;
const superagent = require('superagent');

const User = require('../model/User.js');

const url = process.env.API_URL;

const testUser = {
  email: 'exampleuser@test.com',
  password: '123'
};

const newUser = {
  email: 'newuser@test.com',
  password: '321'
};

describe('POST: /api/signup', () => {
  describe('with valid credentials', () => {
    afterEach(() => User.deleteOne({'email': testUser.email}));

    console.log(`${url}/api/signup`);
    it('should return a status code of 200', () => {
      superagent.post(`${url}/api/signup`)
        .send(testUser)
        .then((res) => {
          expect(res).to.be.an('object');
          expect(res.status).to.equal(200);
        })
        .catch((err) => console.error(err));
    });
  });
});

Я пытался использоватьСделано также, это выглядело примерно так:

describe('POST: /api/signup', () => {
  describe('with valid credentials', () => {
    afterEach((done) => {
      User.deleteOne({'email': testUser.email})
        .then(() => done())
        .catch((err) => done(err));
    });

    console.log(`${url}/api/signup`);
    it('should return a status code of 200', (done) => {
      superagent.post(`${url}/api/signup`)
        .send(testUser)
        .end((res, err) => {
          if(err) return done(err);
          expect(res).to.be.an('object');
          expect(res.status).to.equal(200);
        })
        .then(() => done())
        .catch((err) => console.error(err));
    });
  });
});

но каждый раз, когда я запускаю его, вы видите, как он заканчивает тест и переходит к следующему случаю, прежде чем все будет вызвано и возвращено:

Backend-Portfolio:server.js running on port: 8000 +0ms

  USER_ROUTES
    POST: /api/signup
      with valid credentials
        1) should return a status code of 200
  Backend-Portfolio:user-router.js POST: /api/signup +0ms
        2) "after each" hook for "should return a status code of 200"
    GET: /api/login
      with valid credentials
  Backend-Portfolio:user-router.js POST: /api/signup +2s
  Backend-Portfolio:user-router.js setting up new user +50ms
  Backend-Portfolio:User.js generatePasswordHash:normal +0ms
  Backend-Portfolio:User.js generateToken +158ms
  Backend-Portfolio:User.js generateFindHash +1ms
  Backend-Portfolio:user-router.js setting up new user +462ms
  Backend-Portfolio:User.js generatePasswordHash:normal +295ms
  Backend-Portfolio:User.js generateToken +101ms
  Backend-Portfolio:User.js generateFindHash +0ms

Вот маршрут и методы, которые вызываются, если кому-то интересно:

Здесь вы можете увидеть, где вызывается цепочка методов, я превратил этот маршрут в обещание, просто чтобы попробовать другойспособ тестирования.

userRouter.post('/api/signup', jsonParser, (req, res) => {
  debug('POST: /api/signup');

  let password = req.body.password;
  delete req.body.password;

  return new Promise((resolve, reject) => {
    User.findOne({'email': req.body.email})
      .then((user) => {
        if(user){
          if(user.authenticated){
            // NOTE: maybe update all error codes and texts to be very specific
            reject(createError(400, 'this email is already used, please log in with your password'));
          }else{
            user.generatePasswordHash('normal', password)
              .then((user) => user.generateToken())
              .then((token) => resolve(res.json(token)))
              .catch((err) => reject(console.error(err)));
          }
        }
        else{
          debug('setting up new user');
          let user = new User({
            googlePermissions: {authenticated: false, password: null},
            facebookPermissions: {authenticated: false, password: null},
            twitterPermissions: {authenticated: false, password: null},
            authenticated: true,
            email: req.body.email
          });

          user.generatePasswordHash('normal', password)
            .then((user) => user.generateToken())
            .then((token) => resolve(res.json(token)))
            .catch((err) => reject(console.error(err)));
        }
      })
      .catch((err) => reject(console.error(err)));
  });
});

Остальное, вероятно, немного излишне, но здесь вам нужно:

generatePasswordHash:

userSchema.methods.generatePasswordHash = function(type, password){
  debug(`generatePasswordHash:${type}`);

  return new Promise((resolve, reject) => {
    if(!password) reject(createError(400, 'no password was provided'));

    bcrypt.hash(password, 10, (err, hash) => {
      if(err) return reject(err);
      switch(type){
      case 'normal':
        this.password = hash;
        resolve(this);
        break;
      case 'googlePermissions':
        this.googlePermissions.password = hash;
        resolve(this);
        break;
      case 'facebookPermissions':
        this.facebookPermissions.password = hash;
        resolve(this);
        break;
      case 'twitterPermissions':
        this.twitterPermissions.password = hash;
        resolve(this);
        break;
      default:
        return reject(createError(400, `unrecognized password type: ${type}`));
      }
    });
  });
};

generateToken:

userSchema.methods.generateToken = function(){
  debug('generateToken');

  return new Promise((resolve, reject) => {
    this.generateFindHash()
      .then((findHash) => resolve(jsonwebtoken.sign({token: findHash}, process.env.APP_SECRET)))
      .catch((err) => reject(err));
  });
};

generateFindHash:

userSchema.methods.generateFindHash = function(){
  debug('generateFindHash');

  return new Promise((resolve, reject) => {
    this.findHash = crypto.randomBytes(32).toString('hex');
    this.save()
      .then(() => resolve(this.findHash))
      .catch((err) => reject(err));
  });
};

Спасибо всем, кто сделал это так далеко.

...