Правильно издеваться над библиотеками / методами с Jest - PullRequest
1 голос
/ 14 марта 2019

Я пытаюсь написать модульный тест для метода, и у меня возникают некоторые проблемы с тем, чтобы все работало гладко.

Мне нужно протестировать единственный метод public в этом классе, AuthenticateAdminService.authAdmin, который вызывает методы private, которые вызывают сторонние библиотеки, такие как jsonwebtoken и bcrypt.Проблема, с которой я сталкиваюсь, заключается в том, что, когда я пытаюсь сравнить пароли с bcrypt, он возвращается как false во время автоматических испытаний, но true во время ручного тестирования.

Как я должен надежно издеватьсяэти частные методы и библиотеки?Я нашел несколько постов здесь на SO, которые ничего не сделали для меня, возможно, я просто не понял ответы.Я нашел этот пост о ложных библиотеках , который действительно помог на мгновение, пока я не понял, что любая библиотека, которую я использую, обернута в закрытый метод, который не приносит мне пользы в моих тестах, так как я не вызываю напрямуюмакетированная библиотека.

Я думаю, что должен создать макет приватных методов класса AuthenticateAdminService.Протестируйте действительный публичный метод authAdmin и каким-то образом получите вызываемые закрытые методы, вызываемые вместо реальных версий.Любая помощь?

AuthenticateAdminService

class AuthenticateAdminService {

  public static async authAdmin(reqBody: RequestBody, AdminModel: AdminModel): Promise<object> {
    const { username, password } = reqBody
    const adminRow: AdminRow = await AdminModel.findOne({ where: { username } })
    let token: { token?: string } = {}
    if (adminRow !== null) {
      token = await AuthenticateAdminService.checkIfPasswordsMatch(password, adminRow)
    }
    return token
  }


  private static async checkIfPasswordsMatch(plainPassword: string, adminRow: AdminRow): Promise<object> {
    const isPasswordsMatch = await Promise.resolve(bcrypt.compare(plainPassword, adminRow.password))
    let token: object = {}
    if (isPasswordsMatch) {
      const admin: object = AuthenticateAdminService.removePasswordPropFromAdminRow(adminRow)
      token = { token: await AuthenticateAdminService.createToken(admin) }
    }
    return token
  }

  private static removePasswordPropFromAdminRow(adminRow: AdminRow): object {
    const { password, ...admin } = adminRow.dataValues
    return admin
  }

  private static async createToken(admin: object): Promise<string> {
    const token: string = await Promise.resolve(jwt.sign({ admin }, 'expressadminarea'))
    return token
  }

}

AuthenticateAdminService.test.js (не удается)

import { AuthenticateAdminService } from '../../src/services/AuthenticateAdminService/AuthenticateAdminService'

type AdminModel = {
  findOne(where: object): AdminRow
}

type AdminRow = {
  password: string
  dataValues: { password: string }
}

test('authAdmin', async () => {
  const reqBody: { username: string, password: string } = { username: 'foo', password: 'foo' }
  const adminModel: AdminModel = { findOne: (_where) => <AdminRow>{ password: 'foo', dataValues: { password: 'foo' } } }
  const token: { token?: string } = await AuthenticateAdminService.authAdmin(reqBody, adminModel)

  expect(typeof token).toBe('object')
  expect(typeof token.token).toBe('string')  // token.token is undefined
  expect(token.token.length).toBeGreaterThan(0)
})

1 Ответ

1 голос
/ 14 марта 2019

Похоже, вам просто нужно смоделировать ваш adminModel с помощью хэша пароля вместо открытого текста:

test('authAdmin', async () => {
  const reqBody: { username: string, password: string } = { username: 'foo', password: 'foo' }
  const hash = await bcrypt.hash('foo', 10);  // create a hash
  const adminModel: AdminModel = { findOne: (_where) => <AdminRow>{ password: hash, dataValues: { password: hash } } }  // use the hash
  const token: { token?: string } = await AuthenticateAdminService.authAdmin(reqBody, adminModel)

  expect(typeof token).toBe('object')
  expect(typeof token.token).toBe('string')  // Success!
  expect(token.token.length).toBeGreaterThan(0)
})

Кроме того, bcrypt.compare возвращает Promise, чтобы вы могли упроститьэта строка:

const isPasswordsMatch = await bcrypt.compare(plainPassword, adminRow.password);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...