Describe the bug
When using Jest coverage, decorators with additional parameters appear as uncovered :
@Field(type => ID)@Field(type => [Team])@Query(returns => User)@Mutation(returns => User)@Field() are covered.To Reproduce
User class
@ObjectType()
export class User {
@Field(type => ID)
@IsMongoId()
_id!: Types.ObjectId;
@Field()
@IsEmail()
email!: string;
@Field()
@IsString()
name!: string;
@Field(type => [Team])
@IsArray()
teams?: Team[];
}
User resolver
@Resolver(of => User)
export class UserResolver {
constructor(private readonly usersService: UserService) {}
@Query(returns => User)
async user(@Args('id') id: string): Promise<User> {
const user = await this.usersService.findById(id);
if (!user) {
throw new NotFoundException(id);
}
return user;
}
@Query(returns => [User])
async users(): Promise<User[]> {
return await this.usersService.findAll();
}
@Mutation(returns => User)
@UsePipes(new ValidationPipe())
async addUser(
@Args('addUserInput') addUserInput: AddUserInput
): Promise<User> {
return await this.usersService.add(addUserInput);
}
}
Jest output
src/user | 92.54 | 100 | 72.22 | 91.8
user.model.ts | 89.47 | 100 | 0 | 88.24
user.resolver.ts | 86.36 | 100 | 62.5 | 85
Expected behavior
Decorators should be covered
Logs
If applicable, add some console logs to help explain your problem.
You can paste the errors with stack trace that were printed when the error occured.
Environment (please complete the following information):
Additional context
Did I miss something ? I read issue #377 but didn't find a solution.
Thank you !
decorators with additional parameters appear as uncovered
I think that only parameters, not the whole decorator call is uncovered.
If you want to avoid such things, use _type => User or () => User syntax.
It is indeed only with functions as parameters, though @Resolver(of => User) decorator is covered.
I tried both your suggestions, none of them get covered.
@Resolver is always called, the callback of => User only when you use @FieldResolver on some of its methods.
I don't understand how I should unit-test them. I made the following test file for the resolver, so each decorator should get covered, right ?
describe('UserResolver', () => {
let resolver: UserResolver;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [UserResolver, UserService]
}).compile();
resolver = module.get<UserResolver>(UserResolver);
});
it('should be defined', () => {
expect(resolver).toBeDefined();
});
it('should return all users', async () => {
expect(await resolver.users()).toStrictEqual(users);
});
it('should return a single user', async () => {
expect(await resolver.user('5dfb9aedd8b56d001b4c1362')).toBe(users[0]);
});
it('should throw an exception', async () => {
try {
await resolver.user('5dfb9aedd8b56d001b4c1363');
} catch (error) {
expect(error).toBeInstanceOf(NotFoundException);
}
});
it('should add a user', async () => {
expect(await resolver.addUser(addUserInput)).toBe(users[0]);
});
});
Just use:
@Resolver() // without callback
export class UserResolver {}
when you don't have a field resolver.
And
@Field(() => ID) // without args
@IsMongoId()
_id!: Types.ObjectId;
for other cases
I'm sorry, I don't understand everything. Based on what you wrote and the doc, I should :
@Field() when it isn't a simple type (e.g. ID or any complex type I defined elsewhere, but in that case it's not covered)@Resolver() when resolver has field resolvers@Query and @MutationIf this is correct, does it mean that field decorators with complex types and query/mutation can't be covered ?
If this is correct,
Yes
field decorators with complex types and query/mutation can't be covered ?
Why do you think so?
It shows you the lines as not covered because you don't use type or returns parameter in the callback body.
What you don't understand?
I went through the documentation again, I don't get how I should use type and returns parameters
They can't be consumed as their type is void. They acts just like a description, a documentation, to make the code easier to read.
So that's what I'm saying, I can't cover them, right ?
Fuck yes! As I said - use @Resolver() without callback and @Field(() => ID) without args.
Nothing more I can do, so closing this issue 馃敀
I already tried your suggestion to omit args with @Field(() => ID) and @Query(() => User), but it still appears as uncovered.
Thank you for your time anyway.
So please post an issue on the Jest repo that it doesn't properly report coverage for decorators.