e2e Tests for API –

Saving Nerves and Hours

https://github.com/valentinkononov

http://kononov.space/

 

@ValentinKononov

 

Developer, Speaker

 

Straight to the point

  • What do we mean by API Testing?
  • Test Data flow / DB Queries
  • Test input/output data transform
  • Test CRUD operations
  • Test REST Endpoints
  • Test Authentication
  • What is Usual approach to test this?

Integration Tests

  • Test the whole module
  • Test Service
  • Mock dependencies
  • Update Mock dependencies
  • Update Mock dependencies
  • Update Mock dependencies

Test REST API

  • Mock Authentication
  • Mock Database / Data Repository
  • Mock all functions returning data
jest.mock('../../../api/src/user/user.service', () => ({...}));
jest.mock('../../../api/src/color/color.service', () => ({...}));
jest.mock('../../../api/src/record/record.service', () => ({...}));
jest.mock('../../../api/src/track/track.service', () => ({...}));
...

Change function -> new output / arguments

-> fix test

const updateSpy = jest.spyOn(projectService, 'update')
	.mockImplementation(async () => expectedResult as unknown as ProjectDto);

Is there alternative?

based on NestJS framework

// step #1 - initialize API

let app: INestApplication;
beforeAll(async () => {
    const moduleRef = await Test.createTestingModule({
        imports: [AppModule],
    })
        .overrideGuard(AuthGuard)
        .useClass(AuthGuardMock)
        .compile();

    app = moduleRef.createNestApplication();
    await app.init();
});

afterAll(async () => {
    await app.close();
});

e2e Tests for API

based on NestJS framework

// step #2 - mock authentication

class AuthGuardMock implements CanActivate {
    canActivate(context: ExecutionContext): boolean {
        const request = context.switchToHttp().getRequest();
        request.user = testUsers[0];
        return true;
    }
}

e2e Tests for API

based on NestJS framework

// step #3 - call API and test

await request(app.getHttpServer())
	.post(`/projects/${testProject.id}/tasks`)
	.send({
		details: 'test task text',
		userId: testId,
		dueDate: testDueDate,
	})
	.expect(201);

e2e Tests for API

based on NestJS framework

// step #4 - verify data

await request(app.getHttpServer())
        .get(`/project/${testProject.id}`)
        .send()
        .expect(200)
        .expect((res: Response) => {
            const data: ProjectDto = res.body;

            expect(data.id).toBe(testProject.id);
            ...
        });

e2e Tests for API

Pros

  • Easy to fix / no need to fix tests
  • Easy to modify
  • Test the whole workflow
  • The minimal amount of mocks
  • Usually tests are very readable

Cons

  • Can take time to write data creation code
  • Takes time to run tests (API initialization)
  • Need to prepare a minimal database (including one for CI server)
Date.now = (): number => {
        return 1635792963551;
    };

Special trick

const mockGlobalDate = (): Date => {
    const dateMock = new Date(1635792963551);

    global.Date = class DateMock extends Date {
        constructor(...args: any[]) {
            if (args.length) {
                // @ts-ignore
                super(...args);
            } else {
                super(dateMock.getTime());
            }
        }
    } as any;

    Date.now = (): number => {
        return dateMock.getTime();
    };
};

@ValentinKononov

@ValentinKononov

Conclusion

  • Make coding easier - add tests
  • e2e tests make changes faster
  • e2e tests cover the whole flow
  • less mocks
  • more happiness

E2E Tests for API – Saving Nerves and Hours

By Valentin Kononov

E2E Tests for API – Saving Nerves and Hours

Having adequate test coverage means a lot for the good API. But what can make the whole life pathetic is endless mocking of data and functions for integration tests. Every time you've changed the code you need to fix the mock. After several iterations the correct thought is - what's went wrong? Alternative approach is e2e tests for the API. Which require only minimal mocks and data preparation. The rest - pure code of your API. Change the code - e2e test remains the same. This talk is about my experience of switching from integration tests to e2e tests for the API, proc and cons and how I started to feel happy about tests.

  • 232