Cannot spyOn on a primitive value; undefined given in nestJS
Asked Answered
A

2

11

I know this question is asked before but I'm having this error in nestjs when I run service test function

here is my service code

user.service.ts

import { Injectable,HttpException, HttpCode, HttpStatus  } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { User } from './user.entity';
import { UserRegisterAC } from '../application/userRegisterAC';

@Injectable()
export class UserService {

constructor(
@InjectRepository(User)
private readonly userRepository: Repository<User>) {}

async allUsersList(): Promise<User[]> {
 var users = this.userRepository.find();

 if(users==null){
  throw new HttpException("Users not found",HttpStatus.NOT_FOUND)
 }else{
  return users as unknown as User[];
 }
}

async create(userDTO: UserRegisterAC): Promise<User> {
const user = new User();

user.name = userDTO.name;
user.phoneNo = userDTO.phoneNo;
return this.userRepository.save(user);
}
}

user.spec.ts

import { Test, TestingModule } from '@nestjs/testing';
import { UserService } from './user.service';


describe('UserService', () => {
let service: UserService;

beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
  providers: [UserService],
}).compile();

service = module.get<UserService>(UserService);
});

it('should return user array', async() => {
const result = [{id:1,name:'mayur',phoneNo:'9158816325'}];
// @ts-ignore
jest.spyOn(service,'allUsersList').mockImplementation(() => result); 
expect(await service.allUsersList()).toBe(result);
 });
});

In this file I want test allUserlist function in user service which return array of user. user entity contain id,name and phoneNo. when I run test I'm getting error like

Cannot spyOn on a primitive value; undefined given

  17 |     const result = [{id:1,name:'mayur',phoneNo:'9998814695'}];
  18 |     // @ts-ignore
> 19 |     jest.spyOn(service,'allUsersList').mockImplementation(() => result);
     |          ^
  20 |     expect(await service.allUsersList()).toBe(result);
  21 |   });
  22 | });

Here is my jest config

{
 "moduleFileExtensions": ["js", "json", "ts"],
 "rootDir": ".",
 "testEnvironment": "node",
 "testRegex": ".spec.ts$",
 "transform": {
 "^.+\\.(t|j)s$": "ts-jest"

},
"automock": true

}

I tried everything please give some suggestion

Americana answered 10/7, 2020 at 7:50 Comment(0)
S
4

Your allUsersList will endup under the prototype in the service , kindly try

jest.spyOn(UserService.prototype,'allUsersList').mockImplementation(() => result); 
Shantishantung answered 23/11, 2020 at 14:56 Comment(1)
This is what worked for me, but as a side note the .prototype must be added on the imported Class itself, not on its object. So in the case of the question, it should be: jest.spyOn(UserService.prototype,'allUsersList').mockImplementation(() => result)Genesis
N
3

There's a couple of things that I notice here.

  1. you're mocking the class that you're testing, meaning your tests are meaningless. You should instead mock the dependencies of it.

  2. You aren't mocking the dependencies of your class, so Nest cannot instantiate the class for you, meaning you are getting an undefined instead of a class.

To fix this, you'll want to do something like this:

beforeEach(async () => {
  const modRef = await Test.createTestingModle({
    providers: [
      UserService,
      {
        provide: getRepositoryToken(User),
        useClass: Repository,
      }
    ]
  }).compile();
  service = modRef.get(UserService);
  repository = modRef.get<Repository<User>>(getREpositoryToken(User));
});

And now you can mock the repository methods while still using the service to test the coverage.

There's a more in depth answer here and a repository full of test examples here. Feel free to take a look and dive a bit deeper.

Notice answered 10/7, 2020 at 15:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.