Jest TypeError:无法读取未定义的属性(读取“_id”)

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

我试图找出article.controller.js 文件测试失败的原因。但是,找不到原因。

[文件:article.controller.js]

const {
  saveArticle
} = require('../services/article.service');

exports.createArticle = async (req, res, next) => {
  saveArticle(req.user._id, req.body.article)
    .then((savedArticle) => {
      if (savedArticle) {
        return res.status(200).json({ article: savedArticle });
      }
    })
    .catch(next);
};

[文件:article.controller.test.js]

const { createArticle } = require("../../../controllers/article.controller");
var { saveArticle } = require("../../../services/article.service");
const articleServiceHelper = require("../../../services/article.service");

const mockRequest = () => {
  return {
    title: "Sample article title",
    description: "Sample article description",
    body: "Sample article body"
  };
};

const mockResponse = () => {
  return {
    status: jest.fn().mockReturnThis(),
    json: jest.fn().mockReturnThis()
  };
};

const mockNext = jest.fn();

const mockUser = {
  _id: "6368ad4347dkhs"
}

const mockArticle = {
  title: "Sample article title",
  description: "Sample article description",
  body: "Sample article body"
}

describe("Unit tests for article.controller.js file", () => {
  describe("createArticle tests", () => {
    test("If user can create an article", async () => {
      //Arrange
      let mockReq = mockArticle;
      mockReq = { ...mockReq, _id: "6368ad4347dkhs" };
      const mockRes = mockResponse();
      const saveArticleSpy = jest.spyOn(articleServiceHelper, "saveArticle").mockResolvedValue({ article: mockArticle });
      //Act
      await createArticle(mockReq, mockRes, mockNext);
      //Assert
      expect(saveArticleSpy).toHaveBeenCalledTimes(1);
      expect(saveArticleSpy).toHaveBeenCalledWith(mockUser._id, mockArticle);
      expect(mockRes.status).toHaveBeenCalledWith(200);
      expect(mockRes.json).toHaveBeenCalledWith({
        article: mockArticle
      });
      expect(mockNext).toHaveBeenCalled();
    });
  });
});

[输出]

类型错误:无法读取未定义的属性(读取“_id”)

  12 |
  13 | exports.createArticle = async (req, res, next) => {
> 14 |   saveArticle(req.user._id, req.body.article)
     |                        ^
  15 |     .then((savedArticle) => {
  16 |       if (savedArticle) {
  17 |         return res.status(200).json({ article: savedArticle });

  at Object.<anonymous>.exports.createArticle (controllers/article.controller.js:14:24)
  at Object.<anonymous> (__tests__/unit/controllers/article.controller.test.js:41:13)

我想简单地测试 createArticle 函数。这是令人高兴和极端的情况。

node.js unit-testing jestjs
1个回答
0
投票

您的代码有一些问题:

  1. mockReq
    不正确,应该是:
const mockReq = { user: { _id: '6368ad4347dkhs' }, body: { article: mockArticle } }
  1. ./article.controller
    之后应该需要
    jest.spyOn(articleServiceHelper, 'saveArticle')
    模块,以便监视
    saveArticle()
    函数。如果您在
    ./article.controller
    之前需要
    jest.spyOn()
    模块,则解构的
    saveArticle()
    函数是 not 被监视的。

  2. 根据断言,

    articleServiceHelper.saveArticle()
    的模拟解析值应该是
    mockArticle
    而不是
    { article: mockArticle }

  3. createArticle()
    函数应返回
    saveArticle()
    返回的promise,以便您可以使用
    await createArticle()

所以完整的工作示例是:

article.service.js

exports.saveArticle = async (id, article) => {
  throw new Error('Not implemented');
};

article.controller.js

const { saveArticle } = require('./article.service');

exports.createArticle = (req, res, next) => {
  return saveArticle(req.user._id, req.body.article)
    .then((savedArticle) => {
      if (savedArticle) {
        return res.status(200).json({ article: savedArticle });
      }
    })
    .catch(next);
};

article.controller.test.js

const articleServiceHelper = require('./article.service');

const mockResponse = () => {
  return {
    status: jest.fn().mockReturnThis(),
    json: jest.fn().mockReturnThis(),
  };
};

const mockNext = jest.fn();

const mockUser = {
  _id: '6368ad4347dkhs',
};

const mockArticle = {
  title: 'Sample article title',
  description: 'Sample article description',
  body: 'Sample article body',
};

describe('Unit tests for article.controller.js file', () => {
  describe('createArticle tests', () => {
    test('If user can create an article', async () => {
      //Arrange
      const mockReq = { user: { _id: '6368ad4347dkhs' }, body: { article: mockArticle } };
      const mockRes = mockResponse();
      const saveArticleSpy = jest.spyOn(articleServiceHelper, 'saveArticle').mockResolvedValue(mockArticle);
      const { createArticle } = require('./article.controller');
      //Act
      await createArticle(mockReq, mockRes, mockNext);
      //Assert
      expect(saveArticleSpy).toHaveBeenCalledTimes(1);
      expect(saveArticleSpy).toHaveBeenCalledWith(mockUser._id, mockArticle);
      expect(mockRes.status).toHaveBeenCalledWith(200);
      expect(mockRes.json).toHaveBeenCalledWith({ article: mockArticle });
      expect(mockNext).not.toHaveBeenCalled();
    });
  });
});

测试结果:

 PASS  stackoverflow/78011736/article.controller.test.js                                                                                                                                                                                                          
  Unit tests for article.controller.js file
    createArticle tests                                                                                                                                                                                                                                           
      √ If user can create an article (33 ms)                                                                                                                                                                                                                     
                                                                                                                                                                                                                                                                  
-----------------------|---------|----------|---------|---------|-------------------                                                                                                                                                                              
File                   | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s                                                                                                                                                                               
-----------------------|---------|----------|---------|---------|-------------------
All files              |   85.71 |       50 |   66.66 |   85.71 | 
 article.controller.js |     100 |       50 |     100 |     100 | 6
 article.service.js    |      50 |      100 |       0 |      50 | 2
-----------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        1.12 s
Ran all test suites related to changed files.
© www.soinside.com 2019 - 2024. All rights reserved.