我没有得到下面的文件100%的覆盖率,我不知道为什么会发生这种情况...
**问题的重点:**了解为什么Jest不考虑我的测试,这些测试覆盖了Jest抱怨没有覆盖的行。
Jest抱怨以下代码行:26-27,33-34,38-39,45-46
,但是这些行被覆盖了,正如在我将粘贴到生产文件下面的测试文件上可以看到的那样。
26日至27日:
return badRequest(new MissingParamError(field))
}
33-34
return badRequest(new InvalidParamError('confirmPassword'))
}
38-39
return badRequest(new InvalidParamError('email'))
}
45-46
return serverError()
}
以下是我的生产文件:signup.ts
import { badRequest, serverError, ok } from '../../helpers/http-helper'
import {
HttpRequest,
HttpResponse,
Controller,
EmailValidator,
AddAccount
} from './signup-protocols'
import { MissingParamError } from '../../errors/missing-param-error'
import { InvalidParamError } from '../../errors'
export class SignUpController implements Controller {
private readonly emailValidator: EmailValidator
private readonly addAccount: AddAccount
constructor (emailValidator: EmailValidator, addAccount: AddAccount) {
this.emailValidator = emailValidator
this.addAccount = addAccount
}
async handle (httpRequest: HttpRequest): Promise<HttpResponse> {
try {
const bodyFields = ['name', 'email', 'password', 'confirmPassword']
for (const field of bodyFields) {
if (!httpRequest.body[field]) {
return badRequest(new MissingParamError(field))
}
}
const { name, email, password, confirmPassword } = httpRequest.body
if (password !== confirmPassword) {
return badRequest(new InvalidParamError('confirmPassword'))
}
const isValidMail = this.emailValidator.isValid(email)
if (!isValidMail) {
return badRequest(new InvalidParamError('email'))
}
const newAccount = await this.addAccount.add({ name, password, email })
return ok(newAccount)
} catch (err) {
return serverError()
}
}
}
下面是我的测试文件:
import { SignUpController } from './signup'
import { MissingParamError, InvalidParamError, ServerError } from '../../errors'
import { EmailValidator, AddAccount, AddAccountModel, AccountModel } from './signup-protocols'
const makeEmailValidator = (): EmailValidator => {
class EmailValidatorStub implements EmailValidator {
isValid (email: string): boolean {
return true
}
}
return new EmailValidatorStub()
}
const makeAddAccount = (): AddAccount => {
class AddAccountStub implements AddAccount {
async add (account: AddAccountModel): Promise<AccountModel> {
const fakeAccount = {
id: 'valid_id',
name: 'valid_name',
email: 'valid@email.com',
password: 'valid_password'
}
return await new Promise(resolve => resolve(fakeAccount))
}
}
return new AddAccountStub()
}
interface SutTypes {
sut: SignUpController
emailValidatorStub: EmailValidator
addAccountStub: AddAccount
}
const makeSut = (): SutTypes => {
const emailValidatorStub = makeEmailValidator()
const addAccountStub = makeAddAccount()
const sut = new SignUpController(emailValidatorStub, addAccountStub)
return {
sut,
emailValidatorStub,
addAccountStub
}
}
describe('Auth Controller', () => {
beforeEach(() => {
jest.clearAllMocks()
})
test('should return 400 if no name is provided', async () => {
const { sut } = makeSut()
const httpRequest = {
body: {
email: 'any@mail.com',
password: 'any',
confirmPassword: 'any'
}
}
const httpResponse = await sut.handle(httpRequest)
expect(httpResponse.statusCode).toBe(400)
expect(httpResponse.body).toEqual(new MissingParamError('name'))
})
test('should return 400 if no email is provided', async () => {
const { sut } = makeSut()
const httpRequest = {
body: {
name: 'any',
password: 'any',
confirmPassword: 'any'
}
}
const httpResponse = await sut.handle(httpRequest)
expect(httpResponse.statusCode).toBe(400)
expect(httpResponse.body).toEqual(new MissingParamError('email'))
})
test('should return 400 if no password is provided', async () => {
const { sut } = makeSut()
const httpRequest = {
body: {
name: 'any',
email: 'any@mail.com',
confirmPassword: 'any'
}
}
const httpResponse = await sut.handle(httpRequest)
expect(httpResponse.statusCode).toBe(400)
expect(httpResponse.body).toEqual(new MissingParamError('password'))
})
test('should return 400 if no password confirmation is provided', async () => {
const { sut } = makeSut()
const httpRequest = {
body: {
name: 'any',
email: 'any@mail.com',
password: 'any'
}
}
const httpResponse = await sut.handle(httpRequest)
expect(httpResponse.statusCode).toBe(400)
expect(httpResponse.body).toEqual(new MissingParamError('confirmPassword'))
})
test('should return 400 if an invalid email is provided', async () => {
const { sut, emailValidatorStub } = makeSut()
jest.spyOn(emailValidatorStub, 'isValid').mockReturnValueOnce(false)
const httpRequest = {
body: {
name: 'any',
email: 'invalid_mail@mail.com',
password: 'any',
confirmPassword: 'any'
}
}
const httpResponse = await sut.handle(httpRequest)
expect(httpResponse.statusCode).toBe(400)
expect(httpResponse.body).toEqual(new InvalidParamError('email'))
})
test('should call emailValidator with correct email', async () => {
const { sut, emailValidatorStub } = makeSut()
const isValidSpy = jest.spyOn(emailValidatorStub, 'isValid')
const httpRequest = {
body: {
name: 'any',
email: 'bla@mail.com',
password: 'any',
confirmPassword: 'any'
}
}
await sut.handle(httpRequest)
expect(isValidSpy).toHaveBeenCalledWith('bla@mail.com')
})
test('should return 500 if emailValidator throws', async () => {
const { sut, emailValidatorStub } = makeSut()
jest.spyOn(emailValidatorStub, 'isValid').mockImplementationOnce(() => {
throw new Error()
})
const httpRequest = {
body: {
name: 'any',
email: 'invalid_mail@mail.com',
password: 'any',
confirmPassword: 'any'
}
}
const httpResponse = await sut.handle(httpRequest)
expect(httpResponse.statusCode).toBe(500)
expect(httpResponse.body).toEqual(new ServerError())
})
test('should return 400 if password and confirmPassword do not match', async () => {
const { sut } = makeSut()
const httpRequest = {
body: {
name: 'any',
email: 'invalid_mail@mail.com',
password: 'any',
confirmPassword: 'any1'
}
}
const httpResponse = await sut.handle(httpRequest)
expect(httpResponse.body).toEqual(new InvalidParamError('confirmPassword'))
})
test('should call add with the proper params', async () => {
const { sut, addAccountStub } = makeSut()
const addSpy = jest.spyOn(addAccountStub, 'add')
const httpRequest = {
body: {
name: 'any',
email: 'invalid_mail@mail.com',
password: 'any',
confirmPassword: 'any'
}
}
await sut.handle(httpRequest)
expect(addSpy).toHaveBeenCalledWith({
name: 'any',
email: 'invalid_mail@mail.com',
password: 'any'
})
})
test('should return 500 if AddAccount throws', async () => {
const { sut, addAccountStub } = makeSut()
jest.spyOn(addAccountStub, 'add').mockImplementationOnce(async () => {
return await new Promise((resolve, reject) => reject(new Error()))
})
const httpRequest = {
body: {
name: 'any',
email: 'invalid_mail@mail.com',
password: 'any',
confirmPassword: 'any'
}
}
const httpResponse = await sut.handle(httpRequest)
expect(httpResponse.statusCode).toBe(500)
expect(httpResponse.body).toEqual(new ServerError())
})
test('Should return 200 if the proper data is provided', async () => {
const { sut } = makeSut()
const httpRequest = {
body: {
name: 'valid_name',
email: 'valid@email.com',
password: 'valid_password',
confirmPassword: 'valid_password'
}
}
const httpResponse = await sut.handle(httpRequest)
expect(httpResponse.statusCode).toBe(200)
expect(httpResponse.body).toEqual({
id: 'valid_id',
name: 'valid_name',
email: 'valid@email.com',
password: 'valid_password'
})
})
})
这是我的覆盖率测试脚本的结果:
git push origin master
husky > pre-push (node v16.5.0)
> clean-express@1.0.0 test:ci
> npm test -- --coverage
> clean-express@1.0.0 test
> jest --passWithNoTests --silent --noStackTrace --runInBand "--coverage"
(node:4470) [MDEP001] DeprecationWarning: "MongoMemoryReplSet.getConnectionString" is deprecated, use ".getUri"
(Use `node --trace-deprecation ...` to show where the warning was created)
PASS src/main/Routes/signup-route.test.ts
PASS src/presentation/controllers/signup/signup.spec.ts
PASS src/main/Middlewares/content-type.test.ts
PASS src/main/Middlewares/body-parser.test.ts
PASS src/main/Middlewares/cors.test.ts
PASS src/infra/db/mongodb/account-repository/account.spec.ts
PASS src/infra/cryptography/bcrypt-adapter.spec.ts
PASS src/data/usecases/add-account/db-add-account.spec.ts
PASS src/utils/email-validator-adapter.spec.ts
-------------------------------------|---------|----------|---------|---------|-------------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
-------------------------------------|---------|----------|---------|---------|-------------------------
All files | 95.63 | 83.33 | 100 | 95.63 |
data/usecases/add-account | 100 | 100 | 100 | 100 |
db-add-account.ts | 100 | 100 | 100 | 100 |
infra/cryptography | 100 | 100 | 100 | 100 |
bcrypt-adapter.ts | 100 | 100 | 100 | 100 |
infra/db/mongodb/account-repository | 100 | 100 | 100 | 100 |
account.ts | 100 | 100 | 100 | 100 |
infra/db/mongodb/helpers | 100 | 100 | 100 | 100 |
mongo-helper.ts | 100 | 100 | 100 | 100 |
presentation/controllers/signup | 83.33 | 42.86 | 100 | 83.33 |
signup.ts | 83.33 | 42.86 | 100 | 83.33 | 26-27,33-34,38-39,45-46
presentation/errors | 100 | 100 | 100 | 100 |
base-error.ts | 100 | 100 | 100 | 100 |
index.ts | 100 | 100 | 100 | 100 |
invalid-param-error.ts | 100 | 100 | 100 | 100 |
missing-param-error.ts | 100 | 100 | 100 | 100 |
server-error.ts | 100 | 100 | 100 | 100 |
presentation/helpers | 100 | 100 | 100 | 100 |
http-helper.ts | 100 | 100 | 100 | 100 |
utils | 100 | 100 | 100 | 100 |
email-validator-adapter.ts | 100 | 100 | 100 | 100 |
-------------------------------------|---------|----------|---------|---------|-------------------------
Test Suites: 9 passed, 9 total
Tests: 28 passed, 28 total
Snapshots: 0 total
Time: 6.436 s, estimated 8 s
Enumerating objects: 21, done.
配置
{
"compilerOptions": {
"outDir": "./dist",
"module": "commonjs",
"target": "es2019",
"esModuleInterop": true,
"allowJs": true,
"strictNullChecks": true
}
}
package.json
{
"name": "clean-express",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"start": "sucrase-node src/main/server.ts",
"test:verbose": "jest --passWithNoTests --runInBand",
"test": "jest --passWithNoTests --silent --noStackTrace --runInBand",
"test:unit": "npm test -- --watch -c jest-unit-config.js",
"test:integration": "npm test -- --watch -c jest-integration-config.js",
"test:staged": "npm test -- --findRelatedTests",
"test:ci": "npm test -- --coverage"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"devDependencies": {
"@shelf/jest-mongodb": "^1.2.4",
"@types/bcrypt": "^3.0.1",
"@types/express": "^4.17.13",
"@types/jest": "^26.0.23",
"@types/mongodb": "^3.6.12",
"@types/node": "^15.0.1",
"@types/supertest": "^2.0.11",
"@types/validator": "^13.1.3",
"@typescript-eslint/eslint-plugin": "^4.22.1",
"eslint": "^7.25.0",
"eslint-config-standard-with-typescript": "^20.0.0",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-promise": "^4.3.1",
"git-commit-msg-linter": "^3.1.0",
"husky": "^4.3.8",
"jest": "^26.6.3",
"lint-staged": "^10.5.4",
"prettier": "^2.3.2",
"sucrase": "^3.20.0",
"supertest": "^6.1.4",
"ts-jest": "^26.5.5",
"typescript": "^4.2.4"
},
"dependencies": {
"bcrypt": "^5.0.1",
"express": "^4.17.1",
"fast-glob": "^3.2.7",
"mongodb": "^3.6.6",
"validator": "^13.6.0"
}
}
jest.config.js
module.exports = {
roots: ['<rootDir>/src'],
collectCoverageFrom: [
'<rootDir>/src/**/*.ts',
'!<rootDir>/src/main/**'
],
coverageDirectory: 'coverage',
coverageProvider: 'v8',
testEnvironment: 'node',
transform: {
'.+\\.ts$': 'ts-jest'
},
coveragePathIgnorePatterns: ['protocols', 'domain'],
preset: '@shelf/jest-mongodb'
}
jest-integration.config.js
const config = require('./jest.config')
config.testMatch = ['**/*.test.ts']
module.exports = config
jest-mongodb-config.js
module.exports = {
mongodbMemoryServerOptions: {
binary: {
version: '4.0.3',
skipMD5: true
},
autoStart: false,
instance: {}
}
}
jest-unit-config.js
const config = require('./jest.config')
config.testMatch = ['**/*.spec.ts']
module.exports = config
1条答案
按热度按时间0sgqnhkj1#
尝试更新到jest 27和ts-jest 27