Karma 单元测试 EventEmitter 发射和订阅失败,无法读取未定义的属性“订阅”

Posted

技术标签:

【中文标题】Karma 单元测试 EventEmitter 发射和订阅失败,无法读取未定义的属性“订阅”【英文标题】:Karma unit test EventEmitter emit and subscribe failed, Cannot read property 'subscribe' of undefined 【发布时间】:2020-08-10 12:15:49 【问题描述】:

我是 Angular/Node UT 的新手,目前,我添加了 karma 和 jasmine 来运行单元测试,我的应用程序基于 Angular7 + Node 8,遵循Angular test docs,大多数测试用例运行成功,但有些情况像@Input@Output(EventEmitter) 数据测试失败。 请看我的代码并配置如下:

package.json:

    "jasmine-core": "~2.99.1",
    "jasmine-spec-reporter": "~4.2.1",
    "karma": "~3.0.0",
    "karma-chrome-launcher": "~2.2.0",
    "karma-coverage-istanbul-reporter": "~2.0.1",
    "karma-jasmine": "~1.1.2",
    "karma-jasmine-html-reporter": "^0.2.2"

a.component.ts:

userDetailInit()
    this.lookupService.genericServiceCall1(this.componentIds.componentUserDetail);
    this.lookupService.compomentJsonEmit.subscribe(async o => 
      // logic
    , error => 
      this.error("System Error");
    );
  

lookupService:

    genericServiceCall1(iD) 
      let param = 
        'id': iD
      ;
      this.compomentJsonEmit = new EventEmitter<Object>();
      // getData() is a http request and will return data
      this.commonService.getData('Get', param).subscribe(o =>
        this.compomentJsonEmit.emit(o);
      );
    

在单元测试文件agent-details.component.spec.ts:

describe('UserDetailsComponent', () => 

  let spy = 
    compJSONSpy: jasmine.createSpyObj('lookupService', ['genericServiceCall1']),
  


  beforeEach(async(() => 
    TestBed.configureTestingModule(
      declarations: [ UserDetailsComponent ],
      imports: [FormlyModule.forRoot(), HttpClientTestingModule],
      providers: [
        provide: CommonService, useValue:  spy.comSpy ,
        provide: LookupService, useValue: spy.compJSONSpy
      ],
      schemas: [NO_ERRORS_SCHEMA ]
    ).compileComponents();
    fixture = TestBed.createComponent(UserDetailsComponent);
    component = fixture.componentInstance;
    httpClient = TestBed.get(HttpClient);
    httpTestingController = TestBed.get(HttpTestingController);
  ));


  it('#timeChange(val) should set selectTimeZone to val', () => 
    compJSONSpyReturn = spy.compJSONSpy.genericServiceCall1.and.returnValue(of(spyReturnJson.UserDetailCompJson));
    component.componentIds = 
      componentUserDetail: 1007
    ;

    // error occurred when run component.timeChange(12);
    component.timeChange(12);
    expect(compJSONSpyReturn.calls.any()).toBeDefined();
    expect(component.selectTimeZone).toEqual(12);
  );
);

因果报应报告:

TypeError: Cannot read property 'subscribe' of undefined
    at userDetailsComponent.subscribe [as userDetailInit] (http://localhost:9876/_karma_webpack_/webpack:/src/app/admin/user-details/user-details.component.ts:77:46)
    at userDetailsComponent.userDetailInit [as timeChange] (http://localhost:9876/_karma_webpack_/webpack:/src/app/admin/user-details/user-details.component.ts:109:14)
    at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/src/app/admin/user-details/user-details.component.spec.ts:66:15)
userListComponent #ngOninit() should be run

【问题讨论】:

【参考方案1】:

this.lookupService.compomentJsonEmitundefined

试试:

const compomentJsonEmitSubject = new BehaviorSubject('hello'); // you can mock it how you like instead of 'hello'
describe('UserDetailsComponent', () => 
 let spy = 
    compJSONSpy: jasmine.createSpyObj('lookupService', ['genericServiceCall1']),
  
 spy.compJSONspy.compomentJsonEmit = componentJsonEmitSubject;
 beforeEach(async(() => 
....

然后在你的测试中,如果你想要一个新的值componentJsonEmit,你可以做componentJsonEmitSubject.next('goodbye');

【讨论】:

感谢 AliF50!根本原因如你所说。

以上是关于Karma 单元测试 EventEmitter 发射和订阅失败,无法读取未定义的属性“订阅”的主要内容,如果未能解决你的问题,请参考以下文章

基于karma和jasmine的Angularjs 单元测试

在 Karma 单元测试中模拟导入选择器的值

使用 karma 和 jamis 进行 Angular 单元测试

茉莉花匹配器功能未在 angularjs/karma 单元测试中加载

jasmine matcher函数不在angularjs / karma单元测试中加载

在我的 JSPM 包上使用 JSPM 404 进行 Karma/Jasmine 单元测试