在 Node Express Todo 应用程序中对 CRUD 操作中未定义 response.body 的失败 Jest 测试用例进行故障排除

问题描述 投票:0回答:1

我正在尝试让一些测试用例在节点、快速应用程序中通过。无论我尝试什么,有 2 个测试用例都失败了,分别是

  • 更新任务 › 更新任务 1
  • 通过 ID 获取任务 › 任务名称应该更新

这是一个简单的待办事项应用程序 CRUD,测试用例是用笑话编写的。测试用例失败,因为我得到了response.body undefined

挑战是

During this challenge you will be building on an empty Express Js server and adding the necessary changes for it to become a functional todo list program.
There is a list in index.js called taskList you will use it to store the task objects.
the server has the following routes:
this is what a task looks like:
{
taskName: "string"
status: "string"
created: 'string'
}

get / root of the server, returns "Hello world"

post /task takes a task in the body creates a uuid and saves it like the following in the tasklist
{
    uuid: {
        taskName: "string", status:
        "string", created: "string"
    }
}

GET /tasks Returns all the tasks in a list:
[{UUID: {}}, {UUID:{}}] in a list:

* GET /task/:id 

Returns the task that belongs to the id sent in the path if it exists, otherwise returns null. 
The response structure should be as follows: 
{
    uuid: {
        taskName: "string", 
        status: "string", 
        created:"string" 
    }
}
The response code should be 204. 

PATCH /task/:id

Updates a task by id if it exists in the database, the request body 
will have the keys you need to update in the task object. 
The response code should be 204.

DELETE /task/:id 

Deletes a task from the list if the id exists in the list, otherwise return null. 
The response code should be 204. 

Note: schema.js in the folder models has a schema object of the request, you can use AJV to validate the request body

我尝试将响应作为整个对象发送,但我总是在response.body.taskName中未定义

failed test cases

这是index.test.js

const { expect } = require("@jest/globals");
const request = require("supertest");
const fs = require("fs");
const { validate: validateUUID } = require("uuid");

class test_class {
  constructor() {
    this.test_result = {};
    this.test_count = 0;
  }
  update_report(stdin, stdout, out, display_name = "") {
    let key = "test" + String(this.test_count);
    let test_case = {
      in: `${stdin}`,
      expected: `${stdout}`,
      actual: `${out}`,
      passed: out === stdout,
      display_name: display_name,
    };
    this.test_result[key] = test_case;
    this.test_count++;
  }

  
  writeFile() {
    var testObject = this.test_result;
    fs.writeFileSync(
      "./test_report.json",
      JSON.stringify(testObject, null, 4),
      (err) => {
        if (err) {
          console.error(err);
          return;
        }
      }
    );
  }
}

function isValidUUID(inputString) {
  return validateUUID(inputString);
}


const task = {
  taskName: "Test Task",
  status: "In progress",
  created: "2022-02-14T11:07:05",
};


const update_task = {
  taskName: "new Task",
};

const test_client = new test_class();
let task_id;

const app = require("./index");

describe("Get request to the root", () => {
  test("the response should be ok", async () => {
    const response = await request(app).get("/");
    test_client.update_report("/", "Hello World!", response.text);
    test_client.writeFile();
    expect(response.text).toBe("Hello World!");
  });
});

describe("Create new task", () => {
  test("the returned task id should be a valid uuid", async () => {
    const response = await request(app).post("/task").send(task);
    test_client.update_report("/task", 200, response.statusCode);
    test_client.writeFile();
    // Extract the task ID from the response body
    task_id = response.text; // Use response.text instead of response.body.id

    // Check if the returned ID is a valid UUID
    test_client.update_report(
      "No input for this test",
      true,
      validateUUID(task_id),
      `Check if the returned ID is a valid UUID but recived ${task_id}`
    );
    test_client.writeFile();

    // Assertions
    expect(validateUUID(task_id)).toBe(true);
    expect(response.statusCode).toBe(200);
  });
});

describe("Get task by ID", () => {
  console.log("Get task by ID 0");
  test("the returned task should contain the right taskName", async () => {
    const response = await request(app).get(`/task/${task_id}`);
    test_client.update_report(`/task/${task_id}`, 200, response.statusCode);
    test_client.update_report(`/task/${task_id}`, task.taskName, response.text);
    test_client.writeFile();
    expect(response.text).toEqual(task.taskName);
  });
});

describe("Get All Tasks", () => {
  test("should return an array with the length of ", async () => {
    const response = await request(app).get(`/tasks`);
    test_client.update_report(`/tasks`, 200, response.statusCode);
    test_client.update_report(`/task/${task_id}`, 1, response.body.length);
    test_client.writeFile();
    expect(1).toEqual(response.body.length);
  });
});

describe("Update Task", () => {
  test("Update a task 1", async () => {
    const response = await request(app)
      .patch(`/task/${task_id}`)
      .send(update_task);
    test_client.update_report(`/task/${task_id}`, 204, response.statusCode);
    test_client.writeFile();
    expect(response.body.taskName).toEqual(task.taskName);
  });
});

describe("Get task by ID", () => {
  test("the taskName should be updated", async () => {
    const response = await request(app).get(`/task/${task_id}`);
    test_client.update_report(`/task/${task_id}`, 200, response.statusCode);
    test_client.update_report(
      `/task/${task_id}`,
      update_task.taskName,
      response.body.taskName
    );
    test_client.writeFile();
    expect(response.body.taskName).toEqual(update_task.taskName);
  });
});

describe("Get task by ID", () => {
  test("the taskName should be updated", async () => {
    const response = await request(app).delete(`/task/${task_id}`);
    test_client.update_report(`/task/${task_id}`, 204, response.statusCode);
    test_client.writeFile();
    expect(response.statusCode).toEqual(204);
  });
});

这是index.js

const express = require("express");
const bodyParser = require("body-parser");
const { v4: uuidv4, validate: validateUUID } = require('uuid');
const Ajv = require("ajv");
const taskSchema = require("./models/schema");

const app = express();
app.use(bodyParser.json());

let taskList = [];

// Create an AJV instance and compile the schema
const ajv = new Ajv();
const validateTask = ajv.compile(taskSchema);


// GET / (root of the server)
app.get('/', (req, res) => {
  res.send('Hello World!');
});

// POST /task - Create a new task
app.post('/task', (req, res) => {
  const task = req.body;
  // Validate the request body against the schema
  const valid = validateTask(task);
  if (!valid) {
    return res.status(400).send(validateTask.errors);
  }

  const taskId = uuidv4();

  taskList.push({ [taskId]: { ...task, uuid: taskId } });
  res.status(200).send(taskId);
});

// GET /tasks - Retrieve all tasks
app.get('/tasks', (req, res) => {
  res.send(taskList);
});


// GET /task/:id - Retrieve a specific task by ID
app.get('/task/:id', (req, res) => {
  const taskId = req.params.id;
  const index = taskList.findIndex(task => task[taskId]);
  if (index !== -1) {
    res.status(200).send(taskList[index][taskId].taskName);
  } else {
    res.sendStatus(204);
  }
});

// // PATCH /task/:id - Update a specific task by ID
app.patch('/task/:id', (req, res) => {
  const taskId = req.params.id;
  const update = req.body.taskName;

  // Validate the request body against the schema
  const valid = validateTask(update);
  if (!valid) {
    return res.status(400).send(validateTask.errors);
  }

  // Find the task in taskList based on taskId
  const index =  taskList.findIndex(task => task[taskId])
  if (index !== -1) {
    
    taskList[index][taskId] = { ...taskList[index][taskId], taskName: update };

    // Send the updated task name in the response body
    res.status(200).send(taskList[index][taskId]);
  } else {
    res.sendStatus(404); // Not Found if task with given ID doesn't exist
  }
});

// DELETE /task/:id - Delete a specific task by ID
app.delete('/task/:id', (req, res) => {
  // console.log("6");

  const taskId = req.params.id;
  const index = taskList.findIndex(task => task[taskId]);
  if (index !== -1) {
    taskList.splice(index, 1);
    res.sendStatus(204).send(taskList[index]);
  } else {
    res.sendStatus(204);
  }
});

const PORT = process.env.PORT || 3001;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

module.exports = app;

schema.js

const task = {
    type: "object",
    properties: {
        taskName: {type: "string"},
        status: {type: "string"},
        created: {type: "string"}
    },
    required: ["taskName", "status", "created"],
    additionalProperties: false
}

package.json

{
    "name": "express-js-1",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "dependencies": {
            "ajv": "^8.12.0",
            "babel-cli": "^6.26.0",
            "babel-preset-env": "^1.7.0",
            "express": "^4.17.1",
            "jest": "^27.0.6",
            "nodemon": "^3.1.0",
            "superagent": "^6.1.0",
            "supertest": "^6.1.3",
            "uuid": "^9.0.0"
    },
    "devDependencies": {
            "@babel/cli": "^7.22.10",
            "@babel/preset-env": "^7.22.10"
    },
    "scripts": {
            "test": "jest --watchAll=false  --forceExit",
            "start": "nodemon index.js"
    },
    "author": "",
    "license": "ISC"
}
node.js express jestjs ajv
1个回答
0
投票

有两个单独的问题需要解决:

在“更新任务 - 更新任务 1”中,您将更改的 task 与之前版本的 task 进行比较。将期望语句更改为

expect(response.body.taskName).toEqual(update_task.taskName);

在“按 ID 获取任务 - 任务名称应该更新”中,您的测试是因为当您的 GET 方法已返回任务名称属性时,您正在尝试对任务名称属性建立索引。我建议将 GET /task/:id 方法更改为:

app.get('/task/:id', (req, res) => {
  const taskId = req.params.id;
  const index = taskList.findIndex(task => task[taskId]);
  if (index !== -1) {
    res.status(200).send(taskList[index][taskId]);
  } else {
    res.sendStatus(204);
  }
});

请小心,您需要更新第一个“按 ID 获取任务”测试以获取整个任务对象,而不仅仅是任务名称。如果您确实只想返回任务名称,您可以这样编辑失败的测试:

expect(response.body).toEqual(update_task.taskName);
© www.soinside.com 2019 - 2024. All rights reserved.