marchaos / jest-mock-extended

Type safe mocking extensions for Jest https://www.npmjs.com/package/jest-mock-extended
MIT License
828 stars 57 forks source link

I can't mock the resolved value of prisma methods #80

Closed amirhhashemi closed 2 years ago

amirhhashemi commented 2 years ago

I found this library when I was trying to mock PrismaClient which is like a query builder that the prisma ORM creates automatically based on my database schema. The documentation suggested using this library but I have a big problem that I can't figure out its reason.

Let's say I have a table called User with four columns: id, name, email, password (the id is auto-generated). when I want to create a new user with prismaClient.user.create I have this option to select what fields should be returned from this method.

const userData = {
      name: "myname",
      email: "myemail",
      password: "1234",
};

const newUser = prismaClient.user.create({data: userData, select: {name: true, email: true, password: true}})
// newUser = { name: "myname", email: "myemail",  password: "1234"}

But this test fails

type MockedPrisma = DeepMockProxy<PrismaClient>;
const mockedPrisma: MockedPrisma = mockDeep<PrismaClient>();

mockedPrisma.user.create
      .calledWith({
        data: userData,
        select: { name: true, email: true, password: true },
}).mockReturnValue(userData);      // Error: id is missed

Looks like it doesn't consider the parameters that I pass to calledWith. so I have to include all of my table columns in the expected result to just get rid of the type error. I have about 20 columns in my table and doing it is really nasty? is there a workaround for this issue?

arthurgeek commented 2 years ago

@ahhshm I have the same issue, have you found a solution?

amirhhashemi commented 2 years ago

Hello @arthurgeek . No, unfortunately, I haven't found a solution and it's not like there is a solution(that's why I closed this issue). The closest thing I found was ts-mockito. you can use it like this:

import { mock } from "ts-mockito"

const mockedPrisma: PrismaClient = mock(PrismaClient);

when(mockedPrisma.user.create({ data: user, select: { name: true, email: true, password: true }})).thenResolve(user);

In this simple example, it works properly for me but I have problems with it when it comes to more complex situations and queries. Also, it's not maintained properly so I try to stay away from it but, It may work for you, give it a try.

Another option that I haven't tried is to completely ignore the error by adding this line before the error:

// @ts-ignore

I had given up, but now that I see that others have the same problem, I try again to find a solution. let me know if you found something better.

Sytten commented 2 years ago

What prisma does to create a return type that is only what the select requested is quite complex and it changes all the time. So I don't think this library should even bother supporting it, if it is even possible since the typescript compiler sometimes has trouble inferring the generics especially when they are not directly related like here (we have two chained functions). I would just do .mockReturnValue(userData as any) and be done with it.

amirhhashemi commented 2 years ago

Thank you @Sytten. You are right.