【问题标题】:How to cover Jasmine unit test for RxJS subject in angular如何以角度覆盖 RxJS 主题的 Jasmine 单元测试
【发布时间】:2020-05-12 22:36:49
【问题描述】:

我是非常新的 Jasmine 单元测试用例。我的场景可能很简单,但我不确定如何为下面的课程涵盖 ngInit 的测试用例。谁能帮帮我,

export class Component1 implements OnInit {
    details$: Observable<any>; 
    name: string; 
    error: string 

    constructor(private service1: Service1, private service2: Service2) { }

    ngOnInit() {
       this.service1.service1Subject.subscribe( info => {
            if(info['url']){
                this.details$ = this.service2.get(info['url'])
                this.details$.subscribe(
                 (info) => { this.name = info['name']}; 
                 (error) => { this.erro = error['error']}; 
                ); 
            }  
       }); 
    }
}

测试用例:

describe('Component1', () => {
  let component: Component1;
  let fixture: ComponentFixture<Component1>;

  beforeEach(async(() => {
   TestBed.configureTestingModule({
     declarations: [Component1],
     imports: [
       HttpClientTestingModule, CommonModule
     ],
     providers: [Service1, Service2]
   })
     .compileComponents();
   }));

   beforeEach(() => {
    fixture = TestBed.createComponent(Component1);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should call Get Data', () => {
      const service2: Service2 = TestBed.get(Service2);
      const spy = jest.spyOn(service2, 'get').mockImplementation(() => {
          return {
             info :  [...],
              name : ''  
          }
      });
      component.ngOnInit();
      expect(spy).toHaveBeenCalled();
  });
});

这里的问题是,我不确定如何模拟 service1,RxJS 主题。请有人帮助我。

【问题讨论】:

  • 在您尝试使用 observable 测试您的代码之前,我建议您更深入地了解您可以使用的运算符。嵌套subscribe 是一种巨大的代码气味,您应该使用switchMapconcatMapmergeMap

标签: angular jasmine jestjs karma-jasmine angular-test


【解决方案1】:

我看到您正在使用 Jest,但这是我设置组件测试的方式,这些测试使用公开 Subject 的服务。

  1. 为您的所有服务创建模拟
  2. 在您的测试模块中提供它们
  3. 模拟实现以控制数据流
  4. 执行你的断言

    describe('Component1', () => { 
        let component: Component1;
        let fixture: ComponentFixture<Component1>;
    
        //create mock service objects
        let service1Mock = jasmine.createSpyObj('service1', ['toString']);
        let service2Mock = jasmine.createSpyObj('service2', ['get']);
    
        beforeEach(async(() => {
            TestBed.configureTestingModule({
                declarations: [Component1],
                imports: [
                    HttpClientTestingModule,
                    CommonModule
                ],
                providers: [
                    //Set up the dependency injector, but use the mocks as the implementation
                    { provide: Service1, useValue: service1Mock },
                    { provide: Service2, useValue: service2Mock }
                ]
            }).compileComponents();
        }));
    
        beforeEach(() => {
            //add an observable to your service
            //this will also help reset the observable between each test
            service1Mock.service1Subject = new Subject<any>(); 
        });
    
        beforeEach(() => {
            fixture = TestBed.createComponent(Component1);
            component = fixture.componentInstance;
            fixture.detectChanges();
        });
    
        it('should get the data', () => {
            //configure the mock implementation of "service2.get" to successfully return data
            //You can alternatively use "throw({error: 'some_error'})" to test your "error" case
            service2Mock.get.and.returnValue(of({name: 'some_name'}));
    
            //tell the mock to emit some data!
            service1Mock.service1Subject.next( {url: 'some_url'} );
    
            //Your component subcriptions should handle the event, perform whatever test needs to do
        });
    });
    

我知道 Jasmine 计划让 create spy objects with attributes 成为可能,但我自己并没有真正使用它。

顺便说一句,如果您没有在模板中使用details$,您可以完全消除该变量。

ngOnInit(){
    this.service1.service1Subject.subscribe( info => {
        if(info['url']){
            this.service2.get(info['url']).subscribe(
                (info) => { this.name = info['name']}; 
                (error) => { this.error = error['error']}; 
            ); 
        }  
    });
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-06-30
    • 2021-03-29
    • 2022-10-20
    • 2020-06-05
    • 1970-01-01
    • 2021-05-21
    • 1970-01-01
    • 2021-08-19
    相关资源
    最近更新 更多