在我的其余架构中,有一个控制器(处理http请求)和一个服务(提供数据的业务逻辑)。
为了测试控制器,我试图对服务进行存根以提供固定的响应,但是我不明白如何对需要自定义对象作为参数的方法进行存根(如果该参数是文字,那么它将起作用)。 / p>
使用自定义对象(Farm)存根不起作用,因为并且我没有从服务方法中收到承诺,这是错误消息:
TypeError:无法读取null的属性“ then” 在FarmsController.createFarm(/Users/giovannimarino/Projects/rt-cloud/services/farms/src/farms/farms.controller.ts:17:17)
farms.controller.spec.ts
describe('FarmsController', () => {
const farmsServiceMock: FarmsService = mock(FarmsService);
let controller: FarmsController;
interface TestData {
farm: Farm;
}
let testData: TestData;
beforeEach(() => {
reset(farmsServiceMock);
const farmsServiceMockInstance: FarmsService = instance(farmsServiceMock);
controller = new FarmsController(farmsServiceMockInstance);
testData = {
farm: <Farm> {
name: 'CattD',
imageUrl: 'img/farm-123b341.png',
lang: 'en',
}
};
});
describe('createFarm function', () => {
describe('success', () => {
it('should return HTTP 200 OK', async () => {
when(farmsServiceMock.createFarm(testData.farm)).thenReturn(Promise.resolve<Farm>(testData.farm));
const pathParameters: PathParameter = {
name: 'CattD',
};
const bodyRequest: Body = {
name: testData.farm.name,
imageUrl: testData.farm.imageUrl,
lang: testData.farm.lang
};
const response: ApiResponseParsed<Farm> = await callSuccess<Farm>(controller.createFarm, pathParameters, bodyRequest);
expect(response.statusCode).to.equal(HttpStatusCode.Ok);
});
});
});
});
farm.controller.ts
export class FarmsController {
public constructor(private readonly _service: FarmsService) {
}
public createFarm: ApiHandler = (event: ApiEvent, context: ApiContext, callback: ApiCallback): void => {
if (!event.body) {
throw new Error('Empty input');
}
const input: Farm = <Farm> JSON.parse(event.body);
this._service.createFarm(input)
.then((data: Farm) => {
return ResponseBuilder.created(data, callback); // tslint:disable-line arrow-return-shorthand
})
.catch((error: ErrorResult) => {
if (error instanceof NotFoundResult) {
return ResponseBuilder.notFound(error.code, error.description, callback);
}
if (error instanceof ForbiddenResult) {
return ResponseBuilder.forbidden(error.code, error.description, callback);
}
return ResponseBuilder.internalServerError(error, callback);
});
}
}
farm.service.ts
export class FarmsService {
public constructor(private readonly _repo: FarmsRepository) {
}
public async createFarm(farm: Farm): Promise<Farm> {
try {
return this._repo.create(farm);
} catch (error) {
throw error;
}
}
}
通话成功
export const callSuccess: SuccessCaller = <T>(handler: ApiHandler,
pathParameters?: PathParameter, body?: Body): Promise<ApiResponseParsed<T>> => {
// tslint:disable-next-line typedef (Well-known constructor.)
return new Promise((resolve, reject) => {
const event: ApiEvent = <ApiEvent> {};
if (pathParameters) {
event.pathParameters = pathParameters;
}
if (body) {
event.body = JSON.stringify(body);
}
handler(event, <ApiContext> {}, (error?: Error | null | string, result?: ApiResponse): void => {
if (typeof result === 'undefined') {
reject('No result was returned by the handler!');
return;
}
const parsedResult: ApiResponseParsed<T> = result as ApiResponseParsed<T>;
parsedResult.parsedBody = JSON.parse(result.body) as T;
resolve(parsedResult);
});
});
};
答案 0 :(得分:0)
我遇到了同样的问题,我使用deepEqual()函数将自定义对象作为参数进行了解决。
import {deepEqual, instance, mock, when} from 'ts-mockito';
...
const myCustomObj = {
userId: 123
};
when(mockedObj.myMethod(deepEqual(myCustomObj))).thenResolve(myPromise);
...