NagRock / ts-mockito

Mocking library for TypeScript
MIT License
974 stars 93 forks source link

Mock ngrx store #98

Open Holovin opened 6 years ago

Holovin commented 6 years ago

Hi guys, I trying use ts-mockito for mock ngrx store.

With "plain" selectors its works good: when(storeMock.select(getCurrentTabId)).thenReturn(Observable.of('') as any);

But if selector with input params (like: getCardDetailsById('123')) then I have some problems with mock: when(storeMock.select(getCardDetailsById('123'))).thenReturn(Observable.of({}) as any); - its doesn't work (test runs but failed because mock didn't triggered)

And sure, I can use anything(), but I have several test cases with this "problem" in one test, so can't use anything() and try find a way for solve it.

skusVV commented 6 years ago

i got the same problem, when store has selector with function. for Example:

when(store.select(sitesSelectors.site('something'))).thenReturn(sitesStream as any);

but in this case for fine:

when(store.select(sitesSelectors.something)).thenReturn(sitesStream as any);
mgamsjager commented 5 years ago

Did any of you find a solution?

GillesVercammen commented 4 years ago

I'm still having this problem at the moment, did any of you find a solution to this?

ArtifexEt commented 4 years ago

I've always had problems with mocking store so maybe you should try raw solution from NgRx?

example tutorial:

https://medium.com/ngconf/mockstore-in-ngrx-v7-0-f7803708de4e

GillesVercammen commented 4 years ago

@ArtifexEt Thanks for providing a tutorial, i see that the tutorials makes use of testbed and that is something i would like to avoid for my tests. Thats why i thought ts-mockito would come in handy.

ArtifexEt commented 4 years ago

Back to ts-mockito:

when(storeMock.select(getCardDetailsById('123'))).thenReturn(Observable.of({}) as any)

you would like to return a value based on getCardDetailsById('123')

so in the code you have something similar to:

store.select(getCardDetailsById('123')) -> store.select('something')

I think the problem is what it returns getCardDetailsById('123'). Unfortunately I don't remember what type returns this selector. If it's an object then try:

const selector = getCardDetailsById('123'); //something
when(storeMock.select(deepEqual(selector))).thenReturn(Observable.of({}) as any)

And if it doesn't work that seems to me that the result of this method (selector) is every time different. What then? Use anything() and make expectations based on capture

const [firstArg] = capture(storeMock.select).last();

GillesVercammen commented 4 years ago

Tnx for your response, I tried implementing your first suggestion, didn't manage to get it working.

this is my selector in code: constructor() { this.isBlocked$ = this.store.select(getBlocked(someService.name)); //getBlocked returns a bool }

and in my test i tried mocking it like this now:

  const selector = getBlocked(someServiceMock?.name);
  const isBlocked$ = of(true);
  when(store.select(deepEqual(selector))).thenReturn(of(true));

when i assert like this: expect(component.isBlocked$).toEqual(isBlocked$);

i receive the error that component.isBlocked$, this mean the mock didn't turn out to be working..

I'd like to try your second suggestion but i'm not really understanding the use of anything() and capture

NagRock commented 4 years ago

@GillesVercammen but looks like you are using getBlocked function that is real implementation. ts-mockito mostly is used to mock classes, functions that are imported cannot be mocked by ts-mockito because it runs in runtime. For example jest can mock functions because it test runner and can override imports. Mock needs to get same instance to be able to provide defined return value, anything works for you because it accept everything.