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

How to mock an external package with deepMock #124

Open
ofekisr opened this issue Aug 10, 2023 · 1 comment
Open

How to mock an external package with deepMock #124

ofekisr opened this issue Aug 10, 2023 · 1 comment

Comments

@ofekisr
Copy link

ofekisr commented Aug 10, 2023

I have a module, let's call it myModule that imports @myScope/myPackage
myPackage contains two functions - foo and goo

myModule exports the class 'MyClass' that uses both package functions

when I test MyClass I would like to mock the myPackage with mockDeep of jest-mock-extended
in each test, I would like to mock different return value or implementations of foo and goo

I didn't find a way to do so

// myModule.ts
import { foo, goo } from '@myScope/myPackage'

export class MyClass {
   toTest(): string {
      const a = foo().moo().koo() // that is why I want deepMock
      return goo(a + 'test')
   }
}

// myModule.test.ts
import { foo, goo } from '@myScope/myPackage'
import { MyClass } from './myModule'

describe('', () => {
  let myClass: MyClass

  beforeEach(() => {
    myClass = new MyClass()
  })

  it('should return an empty string', async () => {
    goo.mockReturnValue('')
    const result = myClass.toTest()
    expect(result).toEqual('')
  })
})
@zomnium
Copy link

zomnium commented Aug 24, 2023

Hey!

I was looking into doing something similar, sadly deepMock doesn't seem to support method chaining - which is used here. It would be cool to build something for that. Have you ever looked into that @marchaos?

For now I could recommend you to look into:

  • The concept of dependency injection for your class
  • The mock function mockReturnThis() from Jest

When you combine those you can build something that injects the dependencies into your class. That gives you the ability to replace the actual library with a mocked version. That mocked version returns the object itself, so you can do method chaining just like the library.

The downside of doing this manually is that if the library api changes you have to update your mocks as well. Good to keep that in mind. That would make a mockDeep version for method chaining very useful.

I wasn't sure about mocking goo in your example, but I hope you get the concept with the rough code draft below:

// myModule.ts
import type { myPackage } from '@myScope/myPackage'

export class MyClass {
  constructor(private foo, private goo) {}

   toTest(): string {
      const a = foo().moo().koo() // that is why I want deepMock
      return goo(a + 'test')
   }
}

// app.ts
import { MyClass } from 'myModule.ts'
import { foo, goo } from '@myScope/myPackage'

const app = MyClass(foo, goo)

// myModule.test.ts
import { MyClass } from './myModule'
import { goo } from '@myScope/myPackage'

function createFooMock() {
  return () => ({
    moo: jest.fn().mockReturnThis(),
    moo: jest.fn().mockReturnThis(),
  })
}

describe('', () => {
  let myClass: MyClass

  beforeEach(() => {
    myClass = new MyClass(foo(), goo)
  })

  it('should return an empty string', async () => {
    // Doesn't look like you want to mock this one: goo.mockReturnValue('')
    const result = myClass.toTest()
    expect(result).toEqual('')
  })
})

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