Как устранить ошибку TypeError: невозможно прочитать тело свойства undefined для теста Mocha Chai? - PullRequest
0 голосов
/ 09 июля 2020

Я создал API отдыха, используя express.js, в котором я также публикую sh в kafka. Для этого я использую kafka-node. Ниже мои server.js и app.js и settings-router.js в таком порядке:

server.js:

var app = require('./app');
const http = require('http');
require('dotenv').config();

var port = normalizePort(process.env.PORT || '3999');
app.set('port', port);

var server = http.createServer(app);

server.listen(port);
server.on('error', onError);
server.on('listening', onListening);
server.on('close', onClose);

function normalizePort(val) {
    var port = parseInt(val, 10);

    if (isNaN(port)) {
        return val;
    }

    if (port >= 0) {
        return port;
    }

    return false;
}

const unhandledRejections = new Map();
process.on('unhandledRejection', (reason, promise) => {
    unhandledRejections.set(promise, reason);
    if (reason instanceof Error) {
        console.log(reason,{label: 'ServerError', scope: 'ServerError', message: `Unhandled Rejection.`} );
    }
});
process.on('rejectionHandled', (promise) => {
    unhandledRejections.delete(promise);
});

process.on('uncaughtException', (err, origin) => {
    console.warn(`{"timestamp": "${new Date().toISOString()}","message":"Uncaught Exception.","scope":"ServerError","error":"${err.name}. ${err.message}", "stack":"${err.stack}","origin":"${origin}"}`);
    console.log(err, 'uncaughtException', {label: 'ServerError', origin: origin, scope: 'ServerError'});
});

process.on('warning', (warning) => {
    console.log(warning, 'warning', {label: 'ServerWarning', origin: origin, scope: 'ServerError'});
});

process.on('beforeExit', (code) => {
});


process.on('exit', (code) => {
    logInfo({message: `Process exit event with code ${code}.`, scope: 'Server'});
});

function onError(error) {
    if (error.syscall !== 'listen') {
        throw error;
    }

    var bind = typeof port === 'string'
      ? 'Pipe ' + port
      : 'Port ' + port;

    switch (error.code) {
        case 'EACCES':
            console.log(error, {message: `${bind} requires elevated privileges. `, label: 'ServerError', scope: 'ServerError'});
            process.exit(1);
            break;
        case 'EADDRINUSE':
            console.log(error, {message: `${bind} is already in use. `, label: 'ServerError', scope: 'ServerError'});
            process.exit(1);
            break;
        default:
            throw error;
    }
}

var KafkaServices = require('./services/kafka-services');
kafka = require('kafka-node');
function onListening() {
    var addr = server.address();
    var bind = typeof addr === 'string'
      ? 'pipe ' + addr
      : 'port ' + addr.port;
    console.log('Listening on ' + bind);
    logInfo({message: `Server is Listening on http://localhost:${addr.port}.`, scope: 'Server'});
    kafkaTool = new KafkaServices();
    // Connect to kafka 
    try{
    kafkaTool.producerOn();
    } catch (err) {
        logError(err, 'Error connecting to Kafka', 'Kafka');
    }
}

function onClose() {
    var addr = server.address();
    var bind = typeof addr === 'string'
      ? 'pipe ' + addr
      : 'port ' + addr.port;
    logInfo({message: `Server http://localhost:${addr.port} closed.`, scope: 'Server'});
}

module.exports = {app, onClose} 

app.js:

const express = require('express');
const helmet = require('helmet');
const cookieParser = require('cookie-parser');
var createError = require('http-errors');
var path = require('path');
const settingsRouter = require('./routes/settings-router');
const intercept_request = require('./services/interceptor-service');

const app = express();
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');
app.use(helmet());
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(cookieParser());

app.use(intercept_request);
app.use('/api/v1/settings', settingsRouter);

app.use(function(req, res, next) {
  next(createError(404));
});

app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

settings-router.js:

const express = require('express');
const router = express.Router();
const KafkaServices = require('../services/kafka-services');;
const { isNil } = require('lodash');
const {logInfo, logError} = require('../services/logger');

router.post('/', async (req, res, next) => {
    if (isNil(req['api_key'])) {
        next();
    } else {
        try{
            if (isNil(req.body)) {
                return res.status(400).send({
                    message: 'Request body is empty or null.',
                });
            }
            let payload = {
                topic: process.env.KAFKA_TOPIC || 'fc_ds_devicesettings',
                messages: [], // multi messages should be a array, single message can be just a string or a KeyedMessage instance
                key: null, // string or buffer, only needed when using keyed partitioner
                timestamp: Date.now() // <-- defaults to Date.now() (only available with kafka v0.10+)
            };

            payload.key = isNil(req.body.DeviceId) ? '': req.body.DeviceId;
            payload.messages = JSON.stringify(req.body);

            let kafkaTool = new KafkaServices();
            let result = await kafkaTool.publish(new Array(payload));

            console.log({message: 'Settings API Result.', data: result}, 'API')

        } catch(err){
            console.log(err, { message: 'Error Caught in POST /api/v1/settings.', data: req.body}, 'API')
        }
        return res.send({
            message: 'Settings sent for processing.',
            payload: req.body
        });
    }
}, async (req, res, next) => {
    console.log({message: 'Unauthorized access to settings API', data: req.body}, 'API');
    return res.status(401).send({
        message: 'Unauthorized access to settings API.'
    });
});

router.get('/temp', async (req, res, next) => {
    let kafkaTool = new KafkaServices();
    let result = await kafkaTool.publish(new Array({
        topic: process.env.KAFKA_TOPIC || 'fc_ds_devicesettings',
        messages: 'Test Message',
        key: '1234567',
        timestamp: Date.now()
    }));

    return res.status(200).json({
        message: 'Settings sent for processing.',
        result: result
    });
});

module.exports = router;

Это все работает. Я могу использовать метод POST для полезных данных, и это здорово! Я хочу провести небольшое тестирование с использованием Mocha Chai. Ниже у меня есть свой тест, но я получаю сообщение об ошибке: TypeError: Cannot read property 'body' of undefined at chai.request.post.type.send.then, и я не уверен, почему это так. Любая помощь по этому вопросу будет принята с благодарностью! Спасибо

Тестовый файл: post.js:

process.env.NODE_ENV = 'test';

const server = require('../server');
const app = server.app;
const settingsRouter = require('../routes/settings-router'); 

let chai = require('chai');
let chaiHttp = require('chai-http');
let should = chai.should(); 


chai.use(chaiHttp);

describe('/POST api/v1/settings/', () => {
    it('It should post a full payload', (done) =>{
        chai.request(app)
        .post('localhost:3999/api/v1/settings/')
        .type('Form')
        .send({"DeviceId": "1111111111",
            "DeviceType": 0,
            "Settings": [
              {
                "Key": "Test",
                "Value": "true"
              }
            ]
          })
        .then((err, res) => {
            try{
            console.log(res.body);
            res.should.have.status(200);
            res.body.should.be.a('object');
            res.body.should.have.property('message');
            res.body.should.have.property('payload');
            } catch(err) {
                console.log(err);
            }
        done();
        });
    });
});
...