It is strongly recommended that development be based on test-driven. Test-driven development can effectively precipitate development results and lock potential problems as soon as code changes occur, thus significantly improving the robustness of the codes

On the basis of EggJS, EggBornJS provides a convenient framework for the development based on test-driven

Module test-party

When a new project is created, the module test-party is automatically downloaded to the directory where the project is located. Contains a large number of test-cases and kitchen-sink, and continues to add more content. It is not only convenient to quickly learn all aspects of knowledge points of CabloyJS, but also convenient to quickly start the actual business development

In this tutorial, the following tests are demonstrated. You can use this as an example to continuously expand test cases and increase code coverage as much as possible

  1. Login
  2. Create party
  3. Submit party (change status from draft to normal)
  4. Read party
  5. Delete party

Unit Test

src/suite-vendor/test-party/modules/test-party/backend/test/controller/test.test.js

  1. 1const { app, mockUrl, mockInfo, assert } = require('egg-born-mock')(__dirname);
  2. 2
  3. 3describe('action: atom: party', () => {
  4. 4 it('[atom]', async () => {
  5. 5 app.mockSession({});
  6. 6
  7. 7 // atomClass info
  8. 8 const atomClassModule = mockInfo().relativeName;
  9. 9 const atomClassName = 'party';
  10. 10
  11. 11 // login as root
  12. 12 await app.httpRequest().post(mockUrl('/a/authsimple/passport/a-authsimple/authsimple')).send({
  13. 13 auth: 'root',
  14. 14 password: '123456',
  15. 15 });
  16. 16
  17. 17 // create
  18. 18 let result = await app.httpRequest().post(mockUrl('/a/base/atom/create')).send({
  19. 19 atomClass: { module: atomClassModule, atomClassName },
  20. 20 });
  21. 21 assert(result.body.code === 0);
  22. 22 const atomKey = result.body.data;
  23. 23
  24. 24 // submit
  25. 25 result = await app.httpRequest().post(mockUrl('/a/base/atom/submit')).send({
  26. 26 key: atomKey,
  27. 27 item: {
  28. 28 atomName: 'party demo',
  29. 29 personCount: 3,
  30. 30 },
  31. 31 });
  32. 32 assert(result.body.code === 0);
  33. 33
  34. 34 // read
  35. 35 result = await app.httpRequest().post(mockUrl('/a/base/atom/read')).send({
  36. 36 key: atomKey,
  37. 37 });
  38. 38 assert(result.body.code === 0);
  39. 39
  40. 40 // delete
  41. 41 result = await app.httpRequest().post(mockUrl('/a/base/atom/delete')).send({
  42. 42 key: atomKey,
  43. 43 });
  44. 44 assert(result.body.code === 0);
  45. 45
  46. 46 });
  47. 47});
Name Description
mockUrl used to construct a complete backend API route
mockInfo used to obtain basic information about the module currently under test. For example, the current module name is test-party, but in order to improve the flexibility of the code, it can be obtained by mockInfo().relativeName
app.mockSession used to mock session environment

Run Test

  1. 1$ npm run test:backend

Code Coverage

  1. 1$ npm run cov:backend

API Route: version/test

Before the test cases are executed, the backend API route version/test of each module will be executed automatically

At this stage, you can prepare some test data for testing (such as role, user, permission, etc.)

Take the module test-party as an example, add the following test data:

  1. Add user demo001
  2. Add user’s login authentication information
  3. Append user demo001 to role registered

src/suite-vendor/test-party/modules/test-party/backend/src/service/version.js

  1. 1async test() {
  2. 2 // create test users: demo001
  3. 3 const users = [
  4. 4 { userName: 'demo001', roleName: 'registered' },
  5. 5 ];
  6. 6 const userIds = [];
  7. 7 for (const user of users) {
  8. 8 // add user
  9. 9 userIds[user.userName] = await this.ctx.meta.user.add({
  10. 10 userName: user.userName,
  11. 11 realName: user.userName,
  12. 12 });
  13. 13 // add auth info for login
  14. 14 await this.ctx.performAction({
  15. 15 method: 'post',
  16. 16 url: '/a/authsimple/auth/add',
  17. 17 body: {
  18. 18 userId: userIds[user.userName],
  19. 19 password: '123456',
  20. 20 },
  21. 21 });
  22. 22 // role
  23. 23 const role = await this.ctx.meta.role.get({ roleName: user.roleName });
  24. 24 // add user role
  25. 25 await this.ctx.meta.role.addUserRole({
  26. 26 userId: userIds[user.userName],
  27. 27 roleId: role.id,
  28. 28 });
  29. 29 }
  30. 30}

app.meta.isTest, app.meta.isLocal

The corresponding codes can be loaded in the specified environment through app.meta.isTest or app.meta.isLocal

For example, the resources in the module test-party can only take effect in the test environment and development environment, but not in the production environment. You can operate as follows:

src/suite-vendor/test-party/modules/test-party/backend/src/models.js

  1. 1const party = require('./model/party.js');
  2. 2const partyType = require('./model/partyType.js');
  3. 3const partyPublic = require('./model/partyPublic.js');
  4. 4
  5. 5module.exports = app => {
  6. 6 const models = {
  7. 7 };
  8. 8 if (app.meta.isTest || app.meta.isLocal) {
  9. 9 Object.assign(models, {
  10. 10 party,
  11. 11 partyType,
  12. 12 partyPublic,
  13. 13 });
  14. 14 }
  15. 15 return models;
  16. 16};