Jest单元测试:检查是否调用了super()函数

5

我有一个自定义的错误类,它扩展了Javascript中内置的Error类。 我遇到的问题是,在我的Jest单元测试中,“super()”方法未被检查是否被调用。

export class AppError extends Error {
  public name: string;
  public message: string;
  public status?: number;
  public data?: any;
  constructor(message: string, status?: number, data?: any) {
    super(); <-- this guy!!
    this.name = 'AppError';
    this.status = status || 500;
    this.message = message;
    this.data = data;
  }
}

有没有任何方法可以测试它?谢谢。

你用什么来对你的代码进行单元测试?一个想法是使用 Jasmine 的 "spies"(我通常使用 Karma+Jasmine 进行单元测试)。 - RoboBear
@RoboBear 我正在使用 Jest。 - supergentle
看起来可以在类似于super.methodA()的方法上使用spy。但是它不能对super()方法本身进行监视。 - supergentle
通常最好测试影响本身,而不是说“X被调用了”。 - loganfsmyth
@loganfsmyth 实际上,最好同时测试两者,额外的断言可以使测试更加强大且故障排除更容易。但在这种情况下,测试是否调用了super()是多余的,因为它与类的工作方式有关。 - Estus Flask
@supergentle 如何在类似于super.methodA()的方法中使用spy? - Anat Eliahu
1个回答

7
在原生的ES6类或使用Babel转译的类中,无需检查是否调用了super()
在子类构造函数中不调用super将导致类实例化时出错:

ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

Babel也提供了保障
function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

可以通过模拟子类原型来检查父构造函数是否被调用(这可能对于断言super()参数很有用),例如:

let ParentOriginal;
let ParentMock;

beforeEach(() => {
  ParentOriginal = Object.getPrototypeOf(AppError);
  ParentMock = jest.fn();
  Object.setPrototypeOf(AppError, ParentMock);
});

it('..', () => {
  new AppError(...);
  expect(ParentMock.mock.calls.length).toBe(1);
})

afterEach(() => {
  Object.setPrototypeOf(AppError, ParentOriginal);
});

预计可以在本地类和使用 Babel 转换的类中模拟 super

但是这个测试是多余的,因为缺少 super() 将导致错误。在此处需要测试的仅是 AppError 是否继承自 Error

expect(new AppError(...)).toBeInstanceOf(Error)

1
我遇到的问题是,我使用jest检查单元测试覆盖率时,jest告诉我没有覆盖super()行。那么这是jest的一个bug吗? - supergentle
1
我认为这是一个错误,并建议针对此问题打开一个问题。 - Estus Flask
我知道这已经是一年后的事了...这种方法只适用于Babel吗?我尝试过了,但我的超类构造函数仍然被调用,而不是模拟函数。我已经在基类上测试了功能,现在只需要断言正确的参数是否传递给了超类。 - hvgotcodes
正如答案所说,这也适用于原生类。该答案模拟了一个原型,因为父类是内置的错误(Error)。如果它是自定义类并且类位于不同的模块中,则可以模拟父模块。 - Estus Flask
@estus,你有这方面的例子吗?谢谢! - hvgotcodes
通过使用jest.mock。就像这个问题显示的那样,https://dev59.com/5lUL5IYBdhLWcg3w27Jq。我没有React组件的例子,但这不是特定于React的。如果您在使用jest.mock方面遇到具体问题,请随时发布新的问题。 - Estus Flask

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接