angular - Jasmine createSpyObj 服务未注册调用
问题描述
在阅读了每篇关于 Jasmine 间谍没有注册呼叫的帖子之后,这是我遇到这个问题的代码:
describe( 'shared.FormAutocompleteComponent', () => {
let component: FormAutocompleteComponent;
let fixture: ComponentFixture<FormAutocompleteComponent>;
let displayCtrl: FormControl;
const mockService = jasmine.createSpyObj( 'dynSearchService', ['search', 'lookup'] );
mockService.lookup.and.returnValue( of( { unlocode: 'ZRH/CH', name: 'Zürich' } ) );
mockService.search.and.returnValue( of( [{ unlocode: 'ZRH/CH', name: 'Zürich' }] ) );
beforeEach( async(() => {
TestBed.configureTestingModule( {
declarations: [FormAutocompleteComponent],
providers: [{ provide: DynamicSearchService, useValue: mockService }],
imports: [
NoopAnimationsModule, ReactiveFormsModule,
RouterTestingModule.withRoutes( [] ),
MatInputModule, MatAutocompleteModule, MatIconModule
]
} )
.compileComponents();
} ) );
beforeEach(() => {
displayCtrl = new FormControl();
const group = new FormGroup( {} );
group.addControl( 'foobar', displayCtrl );
fixture = TestBed.createComponent( FormAutocompleteComponent );
component = fixture.componentInstance;
component.config = {
name: 'foobar',
formControl: 'text',
label: 'My foobar',
lookupApi: 'location',
searchApi: 'locations'
};
component.group = group;
fixture.detectChanges();
} );
it( 'should create', () => {
expect( component ).toBeTruthy();
} );
fit( 'should correctly extend single term to wildcard', async(() => {
// arrange
displayCtrl.setValue( 'zrh' );
fixture.detectChanges();
// act
component.search();
// assert
expect( mockService.search ).toHaveBeenCalled();
expect( mockService.search ).toHaveBeenCalledWith( 'zrh*', 'locations' );
} ) );
} );
DynamicSearchService 被注入到 FormAutocompleteComponent 中,并且在组件调用 DynamicSearchService#search 之前直接放置一个 console.log 表明该方法正在被调用。另一个 console.log 显示返回的结果与火车 Jasmine 间谍的结果相匹配。
3396 (Windows 10 0.0.0)]: Connected on socket rlx5hC9uWlNSUz0pAAAA with id 73910165
LOG: 'callDynSearchService with displayCtrl.value=zrh'
LOG: 'callDynSearchService with displayCtrl.value=zrh'
LOG: 'About to run <search> on service with term zr* '
LOG: 'About to run <search> on service with term zr* '
LOG: 'Got results: [{"unlocode":"ZRH/CH","name":"Zürich"}]'
LOG: 'Got results: [{"unlocode":"ZRH/CH","name":"Zürich"}]'
Chrome 67.0.3396 (Windows 10 0.0.0) shared.FormAutocompleteComponent should correctly extend single term to wildcard FAILED
Expected spy dynSearchService.search to have been called.
at <Jasmine>
运行测试
const srv = fixture.debugElement.injector.get( DynamicSearchService );
expect( mockService ).toEqual( srv );
成功,剩下的唯一原因似乎是 .search() 调用从未记录在间谍上。我究竟做错了什么?
编辑,2018 年 6 月 23 日
更改为定义非间谍 mockService(仍然注入'useValue'),然后
fit( 'should correctly extend single term to wildcard', async(() => {
// arrange
let injectedService = TestBed.get( DynamicSearchService );
spyOn( injectedService, 'search' ).and.callThrough();
spyOn( injectedService, 'lookup' ).and.callThrough();
displayCtrl.setValue( 'zrh' );
fixture.detectChanges();
// act
component.search();
// assert
expect( injectedService.search ).toHaveBeenCalled();
} ) );
调试现在显示组件中的服务与“injectedService”是同一个对象。spyOn 所做的代理更改也会显示在组件服务上。但是,Jasmine 仍然记录“搜索”从未被调用过。
解决方案
我猜原因是对 Observable 的 debounceTime() 调用,一些 console.log 语句显示,尽管 async() 和 fixture.whenStable(),但搜索仅在expect() 断言运行后执行。
最终通过切换到 fakeAsync 并使用 tick() 解决了这个问题。
推荐阅读
- ios - 将对象添加到 NSMutableArray - 奇怪的行为
- json - 在 Swift 的 ObjectMapper 中使用 TranfsformType 映射类对象
- regex - 如何从字符串中删除电子邮件地址?
- r - 如何使用 dplyr 根据向量中字符串的存在来变异和赋值
- kotlin - 私有顶级扩展函数和类内部私有扩展函数的区别
- php - Builder.php 第 2405 行中的 BadMethodCallException:调用未定义的方法 Illuminate\Database\Query\Builder::answers()
- sql-server - 我想在 sql server 中将 20080910173240 转换为 2008-09-10T17:32:40.000+0000
- swift - 如何在 xcode 中删除构建警告消息
- redis - 如何将 Redis DB 配置为只读?
- python - 在哪里存储 tns、用户名和密码,以便在 Unix 中与 Python 和 R 一起使用 Oracle DB 连接