gpt4 book ai didi

angular - 如何在 Jest 单元测试中模拟私有(private) ngxs 状态服务依赖项/属性

转载 作者:行者123 更新时间:2023-12-04 13:27:06 25 4
gpt4 key购买 nike

我正在使用 ngxs 来管理我的应用程序的状态。

@State<EmployeesStateModel>({
name: 'employees',
defaults: {
// ...
}
})
@Injectable({
providedIn: 'root'
})
export class EmployeesState {
constructor(private employeesService: EmployeesService) {
}

@Action(GetEmployeesList)
async getEmployeesList(ctx: StateContext<EmployeesStateModel>, action: GetEmployeesList) {

const result = await this.employeesService
.getEmployeeListQuery(0, 10).toPromise();
// ...
}
}
问题
我不明白如何使用 jest 来模拟 EmployeesService我的测试中的依赖项。与 NGXS 测试相关的文档也没有提供任何示例。

I'm just getting started with testing for angular/node applications so I have no idea what I'm doing.


我遵循了从 this SO question 中学到的知识我做了以下测试。
describe('EmployeesStateService', () => {
let store: Store;
let employeesServiceStub = {} as EmployeesService;

beforeEach(() => {
employeesServiceStub = {
getEmployeeListQuery: jest.fn()
};
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
NgxsModule.forRoot([EmployeesState])
],
providers: [

{ provide: EmployeesService, useFactory: employeesServiceStub }
]
});
store = TestBed.inject(Store);
TestBed.inject(EmployeesService);
});

it('gets a list of employees', async () => {
employeesServiceStub = {
getEmployeeListQuery: jest.fn((skip, take) => [])
};

await store.dispatch(new GetEmployeesList()).toPromise();

const list = store.selectSnapshot(state => state.employees.employeesList);
expect(list).toStrictEqual([]);
});
});

这会导致错误 TypeError: provider.useFactory.apply is not a function当我尝试运行测试时。
此外,我在这里设置了 employeesServiceStub 的值在 beforeEach函数,它抛出一个错误,说我分配的值缺少我实际 EmployeesService 中的剩余属性。 .本质上要求我对服务进行完整的模拟实现。这对我来说是非常低效的,因为在每个测试中,我都需要为不同的函数定义不同的模拟实现。
TS2740: Type '{ getEmployeeListQuery: Mock ; }' is missing the following properties from type 'EmployeesService': defaultHeaders, configuration, encoder, basePath, and 8 more.
理想情况下,在每个测试中,我应该能够为我的 EmployeesService 的模拟函数定义不同的返回值。在每个测试中,而不必定义该测试不需要的函数的模拟版本。
由于 EmployeesService 中的函数是异步函数,我也不知道如何为函数定义异步返回值。如果有人能对此有所了解,我将不胜感激。
最终解决方案
基于 answer given by Mark Whitfield ,我进行了以下更改以解决我的问题。
describe('EmployeesStateService', () => {
let store: Store;

// Stub function response object that I will mutate in different tests.
let queryResponse: QueryResponseDto = {};

let employeesServiceStub = {
// Ensure that the stubbed function returns the mutatable object.
// NOTE: This function is supposed to be an async function, so
// the queryResponse object must be returned by the of() function
// which is part of rxjs. If your function is not supposed to be async
// then no need to pass it to the of() function from rxjs here.
// Thank you again Mark!
getEmployeesListQuery: jest.fn((skip, take) => of(queryResponse))
};

beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
NgxsModule.forRoot([EmployeesState])
],
providers: [
// Correctly use the useFactory option.
{ provide: EmployeesService, useFactory: () => employeesServiceStub }
]
});
store = TestBed.inject(Store);
TestBed.inject(EmployeesService);
});

it('gets a list of employees', async () => {
// Here I mutate the response object that the stubbed service will return
queryResponse = {
// ...
};

await store.dispatch(new GetEmployeesList()).toPromise();

const list = store.selectSnapshot(state => state.employees.employeesList);
expect(list).toStrictEqual([]);
});
});

最佳答案

您的提供者定义使用 useFactory在你的例子中是不正确的。
你可以把它改成这样:

providers: [
{ provide: EmployeesService, useFactory: () => employeesServiceStub }
]
您可以使用 useValue对于您的提供者,但这意味着您无法重新分配您在 beforeEach 中初始化的模拟。 ,但必须改变它:
providers: [
{ provide: EmployeesService, useValue: employeesServiceStub }
]
// then in your test...
employeesServiceStub..getEmployeeListQuery = jest.fn(....
employeesServiceStub的重新分配实际上可能仍然是您测试的一个问题,因此您可以改为改变对象,或者将 TestBed 设置移动到您的测试中。
注意:模拟 NGXS 状态的提供者与任何其他 Angular 服务相同。
关于您问题的第二部分,如果您在说 async 时指的是 observable(我可以从您的用法中推断出),那么您可以创建一个 observable 作为结果返回。例如:
import { of } from 'rxjs';
// ...
employeesServiceStub.getEmployeeListQuery = jest.fn((skip, take) => of([]))
附注。如果你在说 async 时确实是说 promise ,那么你可以将你的方法标记为 async从而得到一个 promise 。例如:
employeesServiceStub.getEmployeeListQuery = jest.fn(async (skip, take) => [])

关于angular - 如何在 Jest 单元测试中模拟私有(private) ngxs 状态服务依赖项/属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67720370/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com