Skip to content
Merged
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
93 changes: 93 additions & 0 deletions packages/tracer/tests/unit/Tracer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -958,6 +958,54 @@ describe('Class: Tracer', () => {
expect(await handler({}, context, () => console.log('Lambda invoked!'))).toEqual('memberVariable:someValue');

});

test('when used as decorator on an async method, the method is awaited correctly', async () => {

// Prepare
const tracer: Tracer = new Tracer();
const newSubsegment: Segment | Subsegment | undefined = new Subsegment('### dummyMethod');

jest.spyOn(tracer.provider, 'getSegment')
.mockImplementation(() => newSubsegment);
setContextMissingStrategy(() => null);
const subsegmentCloseSpy = jest.spyOn(newSubsegment, 'close').mockImplementation();
createCaptureAsyncFuncMock(tracer.provider, newSubsegment);

class Lambda implements LambdaInterface {
public async dummyMethod(): Promise<void> {
return;
}

@tracer.captureLambdaHandler()
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
public async handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): void | Promise<void> {
await this.dummyMethod();
this.otherDummyMethod();

return;
}

public otherDummyMethod(): void {
return;
}

}

// Act
const lambda = new Lambda();
const otherDummyMethodSpy = jest.spyOn(lambda, 'otherDummyMethod').mockImplementation();
const handler = lambda.handler.bind(lambda);
await handler({}, context, () => console.log('Lambda invoked!'));

// Assess
// Here we assert that the otherDummyMethodSpy method is called before the cleanup logic (inside the finally of decorator)
// that should always be called after the handler has returned. If otherDummyMethodSpy is called after it means the
// decorator is NOT awaiting the handler which would cause the test to fail.
expect(otherDummyMethodSpy.mock.invocationCallOrder[0]).toBeLessThan(subsegmentCloseSpy.mock.invocationCallOrder[0]);

});

});

describe('Method: captureMethod', () => {
Expand Down Expand Up @@ -1241,6 +1289,51 @@ describe('Class: Tracer', () => {

});

test('when used as decorator on an async method, the method is awaited correctly', async () => {

// Prepare
const tracer: Tracer = new Tracer();
const newSubsegment: Segment | Subsegment | undefined = new Subsegment('### dummyMethod');

jest.spyOn(tracer.provider, 'getSegment')
.mockImplementation(() => newSubsegment);
setContextMissingStrategy(() => null);
const subsegmentCloseSpy = jest.spyOn(newSubsegment, 'close').mockImplementation();
createCaptureAsyncFuncMock(tracer.provider, newSubsegment);

class Lambda implements LambdaInterface {
@tracer.captureMethod()
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
public async dummyMethod(): Promise<void> {
return;
}

public async handler<TEvent, TResult>(_event: TEvent, _context: Context, _callback: Callback<TResult>): Promise<void> {
await this.dummyMethod();
this.otherDummyMethod();

return;
}

public otherDummyMethod(): void {
return;
}
}

// Act
const lambda = new Lambda();
const otherDummyMethodSpy = jest.spyOn(lambda, 'otherDummyMethod').mockImplementation();
const handler = lambda.handler.bind(lambda);
await handler({}, context, () => console.log('Lambda invoked!'));

// Here we assert that the subsegment.close() (inside the finally of decorator) is called before the other otherDummyMethodSpy method
// that should always be called after the handler has returned. If subsegment.close() is called after it means the
// decorator is NOT awaiting the method which would cause the test to fail.
expect(subsegmentCloseSpy.mock.invocationCallOrder[0]).toBeLessThan(otherDummyMethodSpy.mock.invocationCallOrder[0]);

});

test('when used as decorator together with another external decorator, the method name is detected properly', async () => {

// Prepare
Expand Down