Egg: 问题:请问在单元测试里,如何 mock egg-grpc-client?

Created on 24 Oct 2018  ·  8Comments  ·  Source: eggjs/egg

可不可以给个最小的示例?谢谢!

Most helpful comment

之前想复杂了。最终的可行的测试是这样的:

import { app, mock } from 'egg-mock/bootstrap'

it('xxx', async () => {
    mock(app.grpcClient.get('xxx').yyy.User, 'createAuthCode', () => ({
      data: { authCode: '123456' },
    }))

    const result = await app.httpRequest().post('/v1/auth-code').send({
      phone: { countryCode: '86', number: '18888888888' },
    }).expect(200)

    assert.deepStrictEqual(result.body, { success: true, data: '123456' })
  })

All 8 comments

这个库不是我们维护的。

你可以参考下 https://github.com/eggjs/egg-development-stub

@atian25 感谢!这个库是 js 版的,我的项目是 ts 版的,我试了一下 service stub,会报这样的错误:

TypeError: Class constructor SessionStubService cannot be invoked without 'new'

我的项目结构如下:

  |--service
  |----session.ts
  |--stub
  |----service
  |------session.ts

其中,session.ts 如下:

import { Service} from 'egg';

export default class SessionService extends Service {
    public async isTokenValid(token: string): Promise<string> {
         return this.app.grpcClient.get('xxx').Session.isTokenValid({token});
    }
}

然后在 stub 中的 session.ts 尝试 stub 原来的 SessionService:

import SessionService from '../../service/session';

export default class SessionStubService extends SessionService {
  public async isTokenValid(): Promise<boolean> {
    return true;
  }
}

尝试运行测试 session.test.ts

import * as assert from 'assert';
import { Context } from 'egg';
import { app } from 'egg-mock/bootstrap';

describe('session', () => {
  const frontEndToken = 'FlIhvlnP5qM2yKcdVvOmc3M9DbYAjWsx8QHqQVLCqmd';
  let ctx: Context;
  before(async () => {
    ctx = app.mockContext();
  });

  it('已登录', async () => {
    assert(await ctx.service.session.isTokenValid(frontEndToken) === true);
  });
});

@atian25 上面的问题,我可以通过 app.mockService() 来绕过。请问一下这里的 stub service 和 egg-mock 里的 mockService 有什么区别吗?
在我的 egg 项目里,service 使用 grpc 与其他后端服务通信,在 egg 项目的测试里,我应该使用 stub 还是 mock 更适合呢?

非常感谢你的建议!

@Jeff-Tian mock 是单元测试用的,stub 是打桩

@atian25 我暂时放弃使用 https://github.com/eggjs/egg-development-stub 了,使用 eggMock 的 mockService 能满足单元测试需求。

只是这个 mock 和 stub 的概念,能给更多的解释吗?我看了 Martin Fowler 的 Mocks aren't Stubs,感觉 eggMock 项目里的 mock 其实更像是 Stub。

比如这样的写法:

  app.mockService('user', 'get', () => {
    return {
      name: 'fengmk1',
    };
  });

感觉就是给 user service 的 get 方法打了个桩……

egg-development-stub 的主要场景是:如果定义了一个 ctx.proxy 请求后端的接口,在后端还没准备好的时候,可以 stub 然后本地模拟开发测试用。

egg-mock 则是用来写单元测试的,测试期间需要用到的一些 API 就提供在里面了,没有区分 (mock,stub 的概念)

OK,我大概可以先理解为,egg-development-stub 可以用来做类似契约测试的库。类似轻量级的 pact。正好一直觉得 pact 过于复杂了…… 无意中找到这个,真的是非常感谢了!

之前想复杂了。最终的可行的测试是这样的:

import { app, mock } from 'egg-mock/bootstrap'

it('xxx', async () => {
    mock(app.grpcClient.get('xxx').yyy.User, 'createAuthCode', () => ({
      data: { authCode: '123456' },
    }))

    const result = await app.httpRequest().post('/v1/auth-code').send({
      phone: { countryCode: '86', number: '18888888888' },
    }).expect(200)

    assert.deepStrictEqual(result.body, { success: true, data: '123456' })
  })
Was this page helpful?
0 / 5 - 0 ratings

Related issues

fengmk2 picture fengmk2  ·  44Comments

zlab picture zlab  ·  55Comments

occultskyrong picture occultskyrong  ·  35Comments

andylei18 picture andylei18  ·  35Comments

zrxisme picture zrxisme  ·  44Comments