Jasmine 单元测试,仅在服务中覆盖 属性
Jasmine Unit Test, override only property in service
这是我的组件规范文件。它使用日历服务。在 CalendarService 内部有 weekNames、monthNames、monthLongNames 属性(它们只是字符串数组)。现在... CalendarService 里面有很多方法。我希望能够仅覆盖我的规范文件中的这 3 个属性,但保留其余方法并在规范文件中使用它们。我想覆盖它们的原因是因为它们使用另一个服务来创建(例如 weekNames = [this.translationService.formatMessage(), ... , ... , ...])。
这使得测试具有内部服务的组件变得非常困难。
编辑:
或者另一种解决方案是用模拟服务覆盖翻译服务。但是,translationservice 位于使用我的组件的 CalendarService 中。所以我不知道该怎么做。
describe('FCCalendarComponent', () => {
let component: CalendarWrapperComponent;
let fixture: ComponentFixture<CalendarWrapperComponent>;
let calendarComponent: FCCalendarComponent;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [
FCCalendarComponent,
CalendarWrapperComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
FCBaseModule,
HttpClientModule,
FCTranslateModule,
FCCalendarModule
],
providers: [
FCTranslateLoader,
CalendarService,
FCTranslationService,
{
provider: CalendarService, useValue: {
weekNames: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
monthLongNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
}
},
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CalendarWrapperComponent);
component = fixture.componentInstance;
calendarComponent = fixture.debugElement.children[0].componentInstance;
fixture.detectChanges();
})
it('should create component', () => {
expect(component).toBeTruthy();
});
});
@Component({
selector: 'calendar-wrapper',
template: `
<fc-calendar value="2001.02.02"
minDate="2000.03.03"
maxDate="2002.04.04">
</fc-calendar>
`
})
export class CalendarWrapperComponent {
}
覆盖三个属性(如您所展示的)或模拟翻译服务是一个合法的解决方案。
翻译服务不是“位于”日历服务内,而是注入其中。因此,为了模拟它,您需要使用 provide+useValue 机制,就像您对三个属性所做的那样(也许您必须创建 translationMockService class 并调用 useClass 而不是 useValue)。
解决方案:
如果您的组件中有一个服务,并且该服务内部使用了另一个服务。您可以模拟 'child' 服务,而不是模拟 'parent' 服务。
只需将 'child' 服务添加到像这样的提供商
FCTranslationService,
{
provider: FCTranslationService, useValue: { }
},
并在 beforEach 中用您的模拟服务覆盖它,就像这样
TestBed.overrideProvider(FCTranslationService, { useValue: new TranslateMockService() })
如果你想知道 mock 是什么样子的。
export class TranslateMockService {
formatMessage() {
return;
}
}
模拟只有父服务正在使用的方法,没有其他任何东西。
这是我的组件规范文件。它使用日历服务。在 CalendarService 内部有 weekNames、monthNames、monthLongNames 属性(它们只是字符串数组)。现在... CalendarService 里面有很多方法。我希望能够仅覆盖我的规范文件中的这 3 个属性,但保留其余方法并在规范文件中使用它们。我想覆盖它们的原因是因为它们使用另一个服务来创建(例如 weekNames = [this.translationService.formatMessage(), ... , ... , ...])。 这使得测试具有内部服务的组件变得非常困难。
编辑: 或者另一种解决方案是用模拟服务覆盖翻译服务。但是,translationservice 位于使用我的组件的 CalendarService 中。所以我不知道该怎么做。
describe('FCCalendarComponent', () => {
let component: CalendarWrapperComponent;
let fixture: ComponentFixture<CalendarWrapperComponent>;
let calendarComponent: FCCalendarComponent;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [
FCCalendarComponent,
CalendarWrapperComponent
],
imports: [
BrowserModule,
FormsModule,
ReactiveFormsModule,
FCBaseModule,
HttpClientModule,
FCTranslateModule,
FCCalendarModule
],
providers: [
FCTranslateLoader,
CalendarService,
FCTranslationService,
{
provider: CalendarService, useValue: {
weekNames: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"],
monthNames: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
monthLongNames: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
}
},
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(CalendarWrapperComponent);
component = fixture.componentInstance;
calendarComponent = fixture.debugElement.children[0].componentInstance;
fixture.detectChanges();
})
it('should create component', () => {
expect(component).toBeTruthy();
});
});
@Component({
selector: 'calendar-wrapper',
template: `
<fc-calendar value="2001.02.02"
minDate="2000.03.03"
maxDate="2002.04.04">
</fc-calendar>
`
})
export class CalendarWrapperComponent {
}
覆盖三个属性(如您所展示的)或模拟翻译服务是一个合法的解决方案。
翻译服务不是“位于”日历服务内,而是注入其中。因此,为了模拟它,您需要使用 provide+useValue 机制,就像您对三个属性所做的那样(也许您必须创建 translationMockService class 并调用 useClass 而不是 useValue)。
解决方案: 如果您的组件中有一个服务,并且该服务内部使用了另一个服务。您可以模拟 'child' 服务,而不是模拟 'parent' 服务。 只需将 'child' 服务添加到像这样的提供商
FCTranslationService,
{
provider: FCTranslationService, useValue: { }
},
并在 beforEach 中用您的模拟服务覆盖它,就像这样
TestBed.overrideProvider(FCTranslationService, { useValue: new TranslateMockService() })
如果你想知道 mock 是什么样子的。
export class TranslateMockService {
formatMessage() {
return;
}
}
模拟只有父服务正在使用的方法,没有其他任何东西。