Platform: Cannot override mockstore selector during testing

Created on 18 Oct 2019  路  6Comments  路  Source: ngrx/platform

Once a select stream is created it cannot be overwritten during tests with the mockStore.overrideSelector

Minimal reproduction of the bug/regression with instructions:

I have the following component:

@Component({
  template: `{{ myValue$ | async }}`
})
class MyComponent {
  myValue$ = this.store.select(mySelector);
  // ... other observables

  constructor(private store: Store<any>) {}

  onSomeEvent(): void {
    this.store.dispatch(myAction());
  }
  // ... other event handlers
}

Which I would like to test:

describe('MyComponent', () => {
  let store: MockStore<any>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        MyComponent,
        ...
      ],
      providers: [
        provideMockStore({
          selectors: [{ selector: mySelector, value: 'foo' }],
        })
      ],
    }).compileComponents();
  }));

  beforeEach(() => {
    store = TestBed.get(Store);
    fixture = TestBed.createComponent(MyComponent);
    fixture.detectChanges();
  });

  it('should render bar insteadof foo', () => {
    store.overrideSelector(mySelector, 'bar');
    fixture.detectChanges();
    expect(fixture.debugElement.nativeElement.textContent).toBe('bar');
  });

}

Expected behavior:

The above test should pass, the mockStore.overrideSelector should update the select stream.

Versions of NgRx, Angular, Node, affected browser(s) and operating system(s):

NgRx: 8.4.0

Other information:

The mockstore implementation is now creating the stream, but it does not store any reference of the subject. Mockstore should the reference of the stream and next a new value into it in case of overrideSelector called.

There is a similar issue, but that does not solve the use case defined above: #2121

I would be willing to submit a PR to fix this issue

[x] Yes (Assistance is provided if you need help submitting a pull request)
[ ] No

Most helpful comment

You can use the new mockStore.refreshState() method, which isn't documented yet (https://github.com/ngrx/platform/issues/2154).

You can take a look at https://github.com/ngrx/platform/pull/2148 for an example.

All 6 comments

IMHO the documentation contains all that's needed to support your use case.

https://next.ngrx.io/guide/store/testing#using-mock-selectors

You can use the new mockStore.refreshState() method, which isn't documented yet (https://github.com/ngrx/platform/issues/2154).

You can take a look at https://github.com/ngrx/platform/pull/2148 for an example.

@manklu @timdeschryver

store.pipe(select(mySelector)) can be mocked during tests, but you have no tests mocking store.select(mySelector). If you be kind and look at the code I've linked you can see, it's directly returning a new Subject which won't be refeshed with mockStore.refresState()

@peterreisz could create a reproducable example with it?
We have a test to verify store.select should work - https://github.com/ngrx/platform/blob/master/modules/store/testing/spec/mock_store.spec.ts#L336-L345

@timdeschryver I've just got back to this issue and it's working now, thanks for the help.
Meanwhile I've found a connected minor issue: #2244

@peterreisz I know it's been a while, but do you know what the issue was?
I just ran into the same issue where we can set a selector in the provideMockStore({selectors}) method, but it's not getting overridden when using store.overrideSelector()

Was this page helpful?
0 / 5 - 0 ratings

Related issues

NathanWalker picture NathanWalker  路  3Comments

brandonroberts picture brandonroberts  路  3Comments

bhaidar picture bhaidar  路  3Comments

RichardMisiak picture RichardMisiak  路  3Comments

gperdomor picture gperdomor  路  3Comments