Node.js 使用异步初始化代码进行Mocha测试
我正在为REST客户机库编写测试,该库必须使用OAuth exchange“登录”服务。为了防止我要测试的每个端点都登录,我想写一些“测试设置”,但我不确定该怎么做 我的测试项目结构:Node.js 使用异步初始化代码进行Mocha测试,node.js,unit-testing,typescript,mocha.js,Node.js,Unit Testing,Typescript,Mocha.js,我正在为REST客户机库编写测试,该库必须使用OAuth exchange“登录”服务。为了防止我要测试的每个端点都登录,我想写一些“测试设置”,但我不确定该怎么做 我的测试项目结构: 试验 端点类别1.spec.ts 端点类别2.spec.ts 如果我只有一个“端点类别”,我会有这样的东西: describe('Endpoint category 1', () => { let api: Client = null; before(() => { api
- 试验
- 端点类别1.spec.ts
- 端点类别2.spec.ts
describe('Endpoint category 1', () => {
let api: Client = null;
before(() => {
api = new Client(credentials);
});
it('should successfully login using the test credentials', async () => {
await api.login();
});
it('should return xyz\'s profile', async () => {
const r: Lookup = await api.lookup('xyz');
expect(r).to.be.an('object');
});
});
我的问题:
因为login()方法是这里的第一个测试,所以它可以工作,并且客户机实例也可以用于下面的所有测试。但是,如何进行某种设置,使“登录的api实例”可用于我的其他测试文件?公共代码应在每次之前移动到
:
beforeEach(async () => {
await api.login();
});
此时,应该使用测试凭据成功登录
没有多大意义,因为它不断言任何内容。您看过吗
您可以在测试函数中输入一个done参数,您将得到一个回调,您必须调用它
done()或done(错误/异常)
在之前和之后,也将提供此功能
调用done()时,mocha知道异步代码已经完成
啊。如果您想测试登录,您不应该提供与其他测试的连接,因为在默认配置中无法保证测试顺序
只需测试登录和注销后
如果您需要使用“登录会话”进行更多测试,请使用befores描述一个新的测试。api.login()返回Promise,但是它可能会引发异常,因此我采用这种方式。在那种情况下我还需要资产吗?我还假设beforeach将在该描述体中的所有测试之前执行。您的观点是,测试环境应该始终相同,因此我也应该在每次测试之前重新登录?第一个问题:是的,您需要在另一个用例中断言登录错误,因为它与“登录成功”完全不同第二种情况:单元测试中的一个常见原则是不将多个测试绑定在一起。这意味着您可以一次性执行所有这些测试,或者每次只执行其中一个测试。但是怎么做呢?这就是重点。我们存根,我们模拟,我们创建一堆数据。然后呢?在每个测试完成后,我们必须将所有这些重置为零,我的意思是,在我们执行每个测试之前,将系统恢复到状态。此外,Estus Flask是正确的,您的代码完全不是单元测试,而是集成。在单元测试中,我们不使用数据库、网络或任何其他昂贵的东西。我们只是对这些东西存根或嘲笑。更重要的是,我们把一个方法放在一个小盒子里,存根或模拟它需要的每个依赖项,控制输入,最后,我们断言输出。这是单元测试。如果登录不成功,它会抛出一个异常。login方法返回一个解析为void的承诺。同样的问题也适用于这里:我希望避免每次测试都再次登录,因为我实际上只需要登录一次就可以测试所有其他端点。@kentor是的,如果在每次失败之前,这将使所有套件测试失败,这是预期的行为。你所描述的事情永远不应该在单元测试中进行,每个测试都应该是一个新的开始,独立于其他测试,因为做相反的事情会影响测试的状态并导致交叉污染。测试中的OAuth是否是一个昂贵的操作,需要执行真正的XHR请求?是的,对于这种特定情况,OAuth exchange总共包含三个请求。只有在测试它的规范中才调用reallogin()
,应该使用测试凭据成功登录(应该放在不同的descripe
中,以避免在每个规范之前与其他规范共享)。其他规范使用模拟的login
,模拟的方式取决于实现,您可以在api
实例(reallogin()
是可以接受的,但在beforeach中是不可取的,因为单元测试应该是快速的)。这就是我希望正确完成的方式。当然,新客户端(凭据)
也应该在beforeach中完成,以避免交叉污染,这就是为什么我说这些是集成而不是单元测试。有集成测试是一件好事,但它们不能替代单元测试覆盖率。我建议两者都有-它们可以相似和冗余,但它们测试不同的东西。在单元测试中,您可以模拟后端。before
每个description
块执行一次,因此它适合您的描述。我不能建议您这样做,因为在不同的测试之间保持一个公共状态从来都不是一个好的做法,这对于单元、集成和e2e都是一样的。是的,我知道,但为了避免此类回调,我正在使用async/await:)
describe('Endpoint category 1', () => {
let api: Client = null;
beforeEach(() => {
api = new Client(credentials);
});
afterEach(() => {
// You should make every single test to be ran in a clean environment.
// So do some jobs here, to clean all data created by previous tests.
});
it('should successfully login using the test credentials', async () => {
const ret = await api.login();
// Do some assert for `ret`.
});
context('the other tests', () => {
beforeEach(() => api.login());
it('should return xyz\'s profile', async () => {
const r: Lookup = await api.lookup('xyz');
expect(r).to.be.an('object');
});
});
});