簡體   English   中英

使用Mocha / Chai測試Node / Express API

[英]Testing Node/Express API with Mocha/Chai

我目前正在嘗試測試帶有Mocha Chai的Node api。 我遇到了一個測試實際上應該失敗但通過的場景。 如果您想使用它,我將在此處構建當前的API的摘要: 在此處輸入鏈接描述 但是,我仍將遍歷此問題中的代碼。

我正在嘗試使用以下代碼測試控制器:

import chai, { expect } from 'chai';
import chaiHttp from 'chai-http';
import server from '../../src/app';

chai.use(chaiHttp);

describe('Authentication Controller', () => {

  const testUser = {
    email_address: 'test@test.com',
    password: 'test'
  };

  describe('login success', () => {
    it('responds with status 200', done => {
      chai.request(server)
        .post('/api/auth/login')
        .send(testUser)
        .end((err, res) => {
          expect(res).to.have.status(200);
          done();
        });
    });
  });

  describe('login failure', () => {
    it('responds with status 401', done => {
      chai.request(server)
        .post('/api/auth/login')
        .send(testUser.email_address = 'fake@news.com')
        .end((err, res) => {
          expect(res).to.have.status(200);
          done();
        });
    });
  });

});

顯然,我想測試成功的登錄和失敗的登錄嘗試。 但是,來自服務器的兩個響應狀態均為200而事實並非如此。 Postman測試某人嘗試使用不存在的電子郵件地址或密碼不匹配的登錄時的響應狀態時,它將返回狀態401 如果我寫測試

expect(1).to.equal(1) =>測試通過。 expect(1).to.equal(2) =>測試失敗。

這是處理登錄請求的controller功能:

export function login(req, res) {
  User.findOne({email: req.body.email})
    .then(user => {
      if (user && bcrypt.compareSync(req.body.password, user.password)) {
        generateToken(res, user);
      } else {
        res.status(401).json({
          success: false,
          message: 'Incorrect username or password.'
        });
      }
    })
    .catch(err => {
      res.json(err);
    });
}

處理請求的model

export function createUser(req) {
  return db('users').insert(Object.assign(req.body,{password: hashPassword(req.body.password)}))
    .then((id) => db('users').select().where('id', id).first());
}

如您所見,我正在使用Knex.js 我已經建立了一個測試數據庫,並且一切都正確連接,所以對於為什么我的服務器在測試時會以200響應狀態進行響應感到困惑?

我只想說感謝的人誰需要時間來幫助我了解如何mocha chai工作。 我在測試應用程序方面經驗很少,但是我想開始熟悉一下這樣做,因為我認為這是一種很好的做法。

我實際上克隆了您的Github存儲庫,並嘗試運行測試。 據我所知,您的代碼中存在幾個不同的問題,如下所示:

1.從您在問題中發布的控制器功能:

```

export function login(req, res) {
    User.findOne({email: req.body.email})
    .then(user => {
      // [removed because of little relevancy]
    })
    .catch(err => {
      res.json(err);
    });
}

```

問題是res.json(err)行實際上響應了200狀態代碼(即使在這種情況下是錯誤的)。 這是因為當您“發送錯誤對象”時, res.json不會自動為您設置HTTP響應狀態代碼。 這欺騙了客戶端(在本例中為chai-http)認為這是一個成功的請求。 為了正確地回應錯誤狀態代碼,您可以改用以下代碼: res.status(500).json(err)

還需要注意的是,您的其他一些控制器功能也遇到了此問題。


2.從userModels.js文件的第10行開始 ,該行是:

```

return db('users').select().where(req).first();

```

您以不正確的方式使用Knex API。 應該是...where('email', req.email)...這是您的請求失敗的最初原因。


3.您以不同的方式設置了單元測試:

測試編號 1( 登錄成功 ):

```

chai.request(server)
        .post('/api/auth/login')
        .send(testUser)

```

測試編號 2( 登錄失敗 ):

```

chai.request(server)
        .post('/api/auth/login')
        .send(testUser.email_address = 'fake@news.com')

```

所以發生了什么事?

在第一個測試中,您將一個對象傳遞給.send() ,而在第二個測試中,您僅傳遞了一個expression 通過這種方式,模型處理程序userModels.findOne()收到了一個對象,該對象的第一個測試的鍵為email_addresspassword ,但對於第二個測試,則沒有。

同樣,在第一個測試用例中,您發送了testUser.email_address ,但在控制器函數中,您引用了req.body.email

所有這些,除了發行號。 正如我前面提到的,1使測試套件更加復雜,最終導致您的誤解。


免責聲明:

我上面寫的所有內容都是基於您的Github存儲庫中的源代碼的,因此,如果您在推送代碼后已解決了一些問題,並且上面的某些(或全部)觀點不再有效,請忽略。 不過,我希望您已經找到,或者很快就會發現為什么您的代碼沒有按預期運行!

干杯,

我只想在此處發布一個針對我的經驗以及如何幫助我完成所有此設置的答案。 我真正需要在Repo Proj上更改的唯一一件事是我傳遞的用戶對象上的屬性email 我有email_address ,因此正在數據庫中搜索該列,但該列不存在! 所以一旦我改變了,我便開始了正確的道路。

這樣,我就可以通過failed login測試。 但是,我的successful login沒有通過。 原因是因為我使用純字符串密碼為數據庫播種。 因此,當我執行以下條件語句時:

if (user && bcrypt.compareSync(req.body.password, user.password))

它沒有通過,因為bcrypt.comparSync正在尋找經過哈希處理的密碼。 為了使它起作用,我需要在knex文件中要求babel-register 然后,這允許我使用es6並執行我的hashPassword函數:

測試/userSeed.js

import hashPassword from '../../src/helpers/hashPassword';

exports.seed = function(knex, Promise) {
  return knex('users').truncate()
    .then(() => {
      return knex('users')
        .then(() => {
          return Promise.all([
            // Insert seed entries
            knex('users').insert([
              {
                first_name: 'admin',
                last_name: 'admin',
                email: 'admin@admin.com',
                password: hashPassword('test')
              },
              {
                first_name: 'test',
                last_name: 'test',
                email: 'test@test.com',
                password: hashPassword('test')
              }
            ]),
          ]);
        });
    })
};

hashPassword.js

import bcrypt from 'bcrypt';

export default function(password) {
  const saltRounds = 10;
  let salt = bcrypt.genSaltSync(saltRounds);
  return bcrypt.hashSync(password, salt);
}

當我為數據庫添加種子時,這導致了我的用戶密碼的散列。 使用Postman按預期方式測試所有通過和api是否可以正常工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM