如何在组件中模拟ngrx选择器 [英] how to mock ngrx selector in a component

查看:72
本文介绍了如何在组件中模拟ngrx选择器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在组件中,我们使用ngrx选择器来检索状态的不同部分.

In a component, we use a ngrx selector to retrieve different parts of the state.

public isListLoading$ = this.store.select(fromStore.getLoading);
public users$ = this.store.select(fromStore.getUsers);

fromStore.method是使用ngrx createSelector方法创建的.例如:

the fromStore.method is created using ngrx createSelector method. For example:

export const getState = createFeatureSelector<UsersState>('users');
export const getLoading = createSelector(
  getState,
  (state: UsersState) => state.loading
);

我在模板中使用以下可观察对象:

I use these observables in the template:

<div class="loader" *ngIf="isLoading$ | async"></div>
<ul class="userList">
    <li class="userItem" *ngFor="let user of $users | async">{{user.name}}</li>
</div>

我想写一个测试,我可以做类似的事情:

I would like to write a test where i could do something like:

store.select.and.returnValue(someSubject)

为了能够更改主题值并测试组件模板,请再次使用这些值.

to be able to change subject value and test the template of the component agains these values.

事实是,我们努力寻找一种合适的方法来进行测试.既然在组件中调用了select方法两次,并使用两种不同的方法(MemoizedSelector)作为参数,那么如何编写我的"andReturn"方法呢?

The fact is we struggle to find a proper way to test that. How to write my "andReturn" method since the select method is called two times in my component, with two different methods (MemoizedSelector) as arguments?

我们不想使用真实的选择器,因此模拟状态然后使用真实的选择器似乎不是正确的单元测试方法(测试不会被隔离,而是会使用真实的方法来测试组件的行为). /p>

We don't want to use real selector and so mocking a state then using real selector seems not to be a proper unit test way (tests wouldn't be isolated and would use real methods to test a component behavior).

推荐答案

我遇到了同样的挑战,并通过将选择器包装在服务中而一劳永逸地解决了这个问题,所以我的组件只是使用服务来获取其数据,而不是直接经过商店.我发现这清理了我的代码,使我的测试与实现无关,并使模拟变得更加容易:

I ran into the same challenge and solved it once and for all by wrapping my selectors in services, so my components just used the service to get their data rather than directly going through the store. I found this cleaned up my code, made my tests implementation-agnostic, and made mocking much easier:

mockUserService = {
  get users$() { return of(mockUsers); },
  get otherUserRelatedData$() { return of(otherMockData); }
}

TestBed.configureTestingModule({
  providers: [{ provide: UserService, useValue: mockUserService }]
});


但是,在执行此操作之前,我必须先解决您的问题.


Before I did that however, I had to solve the issue in your question.

为您提供的解决方案取决于保存数据的位置.如果您将其保存在constructor中,例如:

The solution for you will depend on where you are saving the data. If you are saving it in the constructor like:

constructor(private store: Store) {
  this.users$ = store.select(getUsers);
}

然后,每次要更改store返回的值时,都需要重新创建测试组件.为此,请按照以下步骤创建函数:

Then you will need to recreate the test component every time you want to change the value returned by the store. To do that, make a function along these lines:

const createComponent = (): MyComponent => {
  fixture = TestBed.createComponent(MyComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
  return component;
};

然后在更改商店间谍返回的值之后调用它:

And then call that after you change the value of what your store spy returns:

describe('test', () => {
  it('should get users from the store', () => {
    const users: User[] = [{username: 'BlackHoleGalaxy'}]; 
    store.select.and.returnValue(of(users));
    const cmp = createComponent();
    // proceed with assertions
  });
});

或者,如果您要在ngOnInit中设置值:

Alternatively, if you are setting the value in ngOnInit:

constructor(private store: Store) {}
ngOnInit() {
  this.users$ = this.store.select(getUsers);
}

事情要容易一些,因为您只需创建一次组件,然后每次想从存储中更改返回值时都只需调用ngOnInit即可:

Things are a bit easier, as you can create the component once and just recall ngOnInit every time you want to change the return value from the store:

describe('test', () => {
  it('should get users from the store', () => {
    const users: User[] = [{username: 'BlackHoleGalaxy'}]; 
    store.select.and.returnValue(of(users));
    component.ngOnInit();
    // proceed with assertions
  });
});

这篇关于如何在组件中模拟ngrx选择器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆