Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CustomPrismaService unit testing #83

Open
coryoso opened this issue Nov 10, 2023 · 2 comments
Open

CustomPrismaService unit testing #83

coryoso opened this issue Nov 10, 2023 · 2 comments

Comments

@coryoso
Copy link

coryoso commented Nov 10, 2023

Hi! Thank you for nestjs-prisma, has been a great addition to our stack so far!

We're using the CustomPrismaService because we need to extend the client. Sadly the unit test setup does not work, i'm struggling with mocking the client. Right now it errors with TypeError: Cannot read properties of undefined (reading 'user') as the client is always undefined.

The userService looks like this:

@Injectable()
export class UsersService {
	constructor( 
		@Inject("PrismaService")
		private readonly prismaService: CustomPrismaService<ExtendedPrismaClient>, 
	) {}

        findOne = async (id: string) => {
	        return this.prismaService.client.user.findFirst({
		        where: { id },
	        })
        }
}

The userService.spec.test file like this:

describe("Usersservice", () => {
	let service: UsersService
	let prisma: DeepMockProxy<CustomPrismaService<ExtendedPrismaClient>>

	beforeEach(async () => {
		const module: TestingModule = await Test.createTestingModule({
			imports: [
				CustomPrismaModule.forRootAsync({
					name: "PrismaService",
					isGlobal: false,
					useFactory: () => {
						return extendedPrismaClient
					},
				}),
			],
			providers: [
				UsersService, 
				{
					provide: PrismaService,
					useValue: {},
				}, 
			],
		})
			.overrideProvider(CustomPrismaService<ExtendedPrismaClient>)
			.useValue(mockDeep<PrismaClient>())
			.compile()

		service = module.get<UsersService>(UsersService)
		prisma = module.get<PrismaService>(PrismaService)
	})

        it("should find a user", async () => {
                const userID = "user-id"
                
                prisma.client.user.findFirst.mockResolvedValueOnce({
	                id: userID,
	                firstName: "John",
	                lastName: "Doe",
	                email: "[email protected]",
                })
                
                expect(service.test(userID)).toEqual(userID)
        })
})

Appreciative of any help, thank you so much!!

@nikola418
Copy link

Hi, I just started learning testing and using jest and I've encountered a similar problem and I think I've gotten a somewhat good grasp on the problem at hand.

So basically, when testing an NestJS that depends on another provider what you need to do is tell NestJS how to construct it (mock it). There are multiple approaches to achieving that but here's what I did:
In your top-most beforeEach where you setup the NestJS testing module create a provider for the Provide Token you wish to mock, here I have an extended prisma client and I used mockDeep because that what Prisma docks suggest to use, I guess it gives better type-safety. Then retreive the mocked client so you can tell jest how you want to mock the return values of the prisma functions you call.

describe(CustomersService.name, () => {
  let customersService: CustomersService;
  let prismaMock: DeepMockProxy<ExtendedPrismaClient>;

  beforeEach(async () => {
    const moduleRef = await Test.createTestingModule({
      providers: [
        CustomersService,
        {
          provide: 'Prisma',
          useValue: <DeepMockProxy<CustomPrismaService<ExtendedPrismaClient>>>{
            client: mockDeep<ExtendedPrismaClient>(),
          },
        },
      ],
    }).compile();

    customersService = moduleRef.get(CustomersService);
    prismaMock =
      moduleRef.get<DeepMockProxy<CustomPrismaService<ExtendedPrismaClient>>>(
        'Prisma',
      ).client;
  });

Then in your describe block of the unit you're testing create a mock value. Here I did it by just constructing a dummy Prisma.Customer[] object and then told the prismaMock.customer.findMany to mock the resolved value to be that instance.


  describe('When findAll is called', () => {
    describe('and findMany returns an array of Customers', () => {
      let customers: Customer[];
      beforeEach(() => {
        customers = [
          {
            id: 1,
            address: '',
            addressLatitude: new Decimal(45),
            addressLongitude: new Decimal(45),
            currency: Currency.RSD,
            paymentMethod: PaymentMethod.OnDelivery,
            rating: new Decimal(0),
            ratingsCount: 0,
            createdAt: new Date(),
            updatedAt: new Date(),
          },
        ];
        mockReset(prismaMock);
        prismaMock.customer.findMany.mockResolvedValue(customers);
      });
      it(`Should return the array of Customers`, async () => {
        expect(await customersService.findAll()).toBe(customers);
      });
    });
  });

Again, I've just started learning testing and using jest, but I hope this helps!

@nikola418
Copy link

If however you don't have an extended client or don't care about type-safety I encourage you to check out this blog: (https://wanago.io/2023/04/03/api-nestjs-unit-tests-prisma/)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants