Open jjteoh-pingspace opened 3 years ago
Maybe this isn't your scenario, but I had a similar problem in a monorepo and I'm sharing the solution I found:
Check that your class's return is with the object in question as an instance of the class you expect in @Type
. I got to this issue because I had the same problem with my tests and found some symptoms:
plainToClass
is inside another library, for some reason the @Type()
decorator doesn't work, it's simply ignored.I don't know how to explain the problem, but I solved it by passing the function that called plainToClass
, as a parameter in the class method that called it directly before.
Example:
packages/libs/my-response.ts
export type DataParser<T> = (data: any) => T;
export class MyResponse {
public constructor(private readonly data: unknown) {}
public getData<T>(parse: DataParser<T>): Promise<T> {
const data = parse(this.data);
return data;
}
}
packages/other-lib/use-my-response.ts
import { plainToClass } from "class-transformer";
import { MyResponse } from "@mypackage/libs/my-response";
const parser = (data: any) => plainToClass(MyClass, data);
// response is now covered in the `@Type()` decorator
const response = new MyResponse(data).getData(parser);
I came across this same issue while trying to implement this package into one of my projects. I am not going to say this is the "best practice" way to fix it, but it did hit my coverage.
jest.mock("class-transformer", () => {
return {
...(jest.requireActual("class-transformer") as Object),
Type: (typeReturn: Function) => {
// Call the internal type return function to satisfy coverage
typeReturn();
// Call the actual type request and return it to still allow the metadata to be set correctly
return jest.requireActual("class-transformer").Type(typeReturn);
},
};
});
I placed that mock in my setup file (setupFilesAfterEnv
) for jest.
Hoping this would be useful to anyone facing similar issue. I used the idea from this thread to come up with a solution:
// dto.ts
export class MyDto {
@IsNotEmpty()
@Type(() => Boolean)
myBooleanFlag: boolean;
...
}
In your spec, create a plain object and convert it to your Dto type using plainToInstance
which you can import from the class-transformer
package (node module):
import { plainToInstance } from 'class-transformer';
...
const obj = {
myBooleanFlag = 'true',
}
const dtoInstance = plainToInstance (MyDto, obj)
By specifying plain values on the object, the @Type decorator would do the required transformation and get picked up in your coverage.
Using Typescript 5 and setting experimentalDecorators: false, emitDecoratorMetadata: false
in my tsconfig.json
solve my coverage problems.
I was trying to write test with Jest, my coverage report complain that the two lines with
@Type()
decorator were not covered.I am looking for the right way(best practice) to write test for those two lines.