supertest mock-fs 使其他测试崩溃

问题描述

对我的 nodejs 后端的一些请求是 Ajax 请求,对于这些路由,我使用令牌身份验证,“令牌保存在 fs 上”。

我使用 jest-supertest 进行测试。

如果我直接测试保存令牌的函数(模拟 fs)它可以工作。

功能

async function savetoken(token) {
    try{
    
        const err = await promisify(fs.writeFile)(
            '/opt/app/tmp/token.txt',token,{encoding: 'utf8',flag: 'w'}
        )

        if(err) throw Error('error in close: ',err)
        else return true

测试://有效

const mock = require('mock-fs');
const { savetoken } = require('../token')
const { readFile } = require('fs').promises

it('makes sure the token is saved',async() => {
    const token = 'theIsThetoken'
    mock({
        '/opt/app/tmp/token.txt': ''
    });

    await savetoken(token)
    const dts = await readFile('/opt/app/tmp/token.txt','utf8')

    mock.restore(); 
    expect(dts).toEqual(token)  
})

但我不想运行单元测试,我想检查完整的请求。问题是,如果我模拟路径的测试和文件崩溃的其他测试。看起来它在所有测试中都嘲笑 fs ......?

路由逻辑

exports.getAddReview = async(req,res,next) => {
    const token = Math.random().toString(36).split('.')[1].slice(0,10)
    try {
        const hash = await encrypt(token)
        const tokenSaved = await savetoken(token)
        if(!tokenSaved) throw Error(REVIEW_CT,' - token is not save')

        res.render('tprmain/edit-review',{
            pageTitle: 'edit-review',path: '/edit-review',editing: false,token: hash
        })
    } catch(e) {
        next(new ProcessError('A system error occured,please try again'))
    }   
}

测试:

it('save token',async() => {
    
    const resp = await global.signin()

    // mock({
    //  '/opt/app/tmp/token.txt': ''
    // });


    await resp
        .get('/add-review')
        .send()
        .expect(200)
    
    // mock.restore();  
})

如果我像上面那样运行测试,我会得到这个错误,这是正常的 fs 不是模拟的。

error from save token:  [Error: ENOENT: no such file or directory,open '/opt/app/tmp/token.txt'] {

所以我取消了模拟此请求的 fs 的注释,但随后所有其他测试(在同一测试文件上)崩溃

// mock({
        //  '/opt/app/tmp/token.txt': ''
        // });
    

错误

 FAIL  controllers/__test__/carsCt.test.js
  ● Test suite Failed to run

    ENOENT: no such file or directory,open '/home/jerome/Documents/code/tprSiang/api/controllers/__test__/carsCt.test.js'

      at runTestInternal (node_modules/jest-runner/build/runTest.js:202:27)

 FAIL  controllers/__test__/picsmainCt.test.js
  ● Test suite Failed to run

    ENOENT: no such file or directory,open 

'/home/jerome/Documents/code/tprSiang/api/controllers/__test__/picsmainCt.test.js'
    
          at runTestInternal (node_modules/jest-runner/build/runTest.js:202:27)
etc...............

如果有人有解决方案,谢谢,因为我想测试完整的路线,而不仅仅是功能

================== 在这里查看完整的测试设置 ==========

jest 设置文件

const { MongoMemoryServer } = require('mongodb-memory-server')
const mongoose = require('mongoose')
const session = require('supertest-session')

const keys = require('../config/keys')
const app = require('../index')

let mongo 
beforeAll(async() => {
    // process.env.NODE_ENV = 'test'

    mongo = new MongoMemoryServer()
    const mongoUri = await mongo.getUri()

    await mongoose.connect(mongoUri,{
        useNewUrlParser: true,useUnifiedTopology: true
    })
})

beforeEach(async() => {
    const collections = await mongoose.connection.db.collections()

    for(let c of collections){
        await c.deleteMany({})
    }
})

afterall(async() => {
    await mongo.stop()
    await mongoose.connection.close()
})

// afterEach(async() => {   
//  mock.restore(); 
// })

global.signin = async() => {
    let testSession = session(app)

    return await new Promise((resolve,reject) => { 
        testSession.post('/postsignin')
            .set('Content-Type','application/x-www-form-urlencoded')
            .send({
                name: keys.adminName1,password: keys.adminPasswordClear
            })
            .end(err => {
                if(err) reject(err)
                resolve(testSession)
            })
    })
} 

无法模拟 fs 的测试文件

const app = require('../../index')
const session = require('supertest-session')
const keys = require('../../config/keys')
const Review = require('mongoose').model('Review')

const mock = require('mock-fs');

//  test get reviews
it('makes sure getReviews need authentification',async() => {
    await session(app)
        .get('/reviews')
        .send()
        .expect('Location','/admin/getsignin')

})

it('get all the reviews',async() => {
    const resp = await global.signin()
    
    await resp
        .get('/reviews')
        .send()
        .expect(200)
})

// test postAddReviews,all token logic is tested separatly
it('add some correct reviews',async() => {
    
    const dataSample = new Review({
        name:'addReview',comment:'comment addReview',picUrl:'http://urlPicture.com',quand: Date.Now()
    })
    const savedDts = await dataSample.save()

    const reviewsDB = await Review.find()

    expect(dataSample.name).toEqual(reviewsDB[0].name)
    expect(dataSample.comment).toEqual(reviewsDB[0].comment)    
    expect(dataSample.picUrl).toEqual(reviewsDB[0].picUrl)  
})

// test the mock,the mock restore is in afterEach() in the setup.js file
// it('test getAddReview',async() => {
//  const resp = await global.signin()
//  mock({
//      '/opt/app/tmp/token.txt': ''
//  });
// 
//  await resp
//      .get('/add-review')
//      .send()
//      .expect(200)
// })
    
// does not work as can test the token in query
// it('add some incorrect picUrl field',async() => {
//  const resp = await global.signin()
//  
//  const dataSample = {
//      name:'addReview',//      comment:'comment addReview',//      nopicUrlfield:'http://urlPicture.com',//      quand: Date.Now()
//  }
// 
//  const response = await resp
//      .post('/add-review')
//      .set('Content-Type','application/x-www-form-urlencoded')
//      .send(JSON.stringify(dataSample))
//      .expect(417)
// })

// test postEditReview
it('makes sure postEditReviews need authentification',async() => {
    await session(app)
        .get('/edit-review/:id')
        .send()
        .expect('Location','/admin/getsignin')

})

it('update a review',async() => {
    const resp = await global.signin()

    // save/set original review
    const dataSample = new Review({
        name:'addReview',quand: Date.Now()
    })
    const reviewSaved = await dataSample.save()

    // create updated review
    const updatedDatas = {
        name:'addReview updated',comment:'comment addReview updated',picUrl:'http://updated.com',quand: Date.Now()
    }
    // save updated datas
    await resp
        .post(`/edit-review/${reviewSaved._id}`)
        .set('Content-Type','application/x-www-form-urlencoded')
        // .send(JSON.stringify(updatedDatas))
        .send(updatedDatas)
        .expect(302)

    // get the reviews
    const reviewsDB = await Review.find()   

    expect(updatedDatas.name).toEqual(reviewsDB[0].name)
    expect(updatedDatas.comment).toEqual(reviewsDB[0].comment)
})

// test getDeleteReview
it('makes sure the getDeleteReview route need auth',async() => {
    await session(app)
        .get('/delete-review/67546')
        .send()
        .expect('Location','/admin/getsignin')
})

it('delete a review',quand: Date.Now()
    })
    const reviewSaved = await dataSample.save()

    // delete the review
    await resp
        .get(`/delete-review/${reviewSaved._id}`)
        .send()

    // get the reviews
    const reviewsDB = await Review.find()   
    
    expect(reviewsDB.length).toEqual(0)
})

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...