【问题标题】:Jasmine/Angular: Testing the reception of a void EventEmitter onInit?Jasmine/Angular:测试 void EventEmitter onInit 的接收?
【发布时间】:2019-11-08 07:14:46
【问题描述】:

我正在为我的一个组件编写单元测试。所述组件具有visible 布尔值,初始化为假。当该布尔属性变为 true 时,组件的 display css 属性从无变为阻塞,使其可见。

由于我的组件是子组件,因此我构建的循环是为了让父组件在技术上“触发”该组件,如下所示:

  • 组件初始化为不可见状态。父母和孩子都连接到如下所示的服务:
    export class SidebarService {

    public toggleSidebar: EventEmitter<void> = new EventEmitter();
    
      constructor() {}

    public showSidebar() {
       this.toggleSidebar.emit();
      }
    }

该服务不需要连接到任何端点,也不需要返回任何数据:发射器充当子组件的“每次点击”信号。

  • 点击父模板中的按钮,父模板调用如下方法:
 toggleSidebar() {
    this.sidebarService.showSidebar();
  }
  • 在我的子组件的 OnInit 上,我写了以下内容:
     ngOnInit() {
        this.sidebarService.toggleSidebar.subscribe(() => {
          this.visible = true;
        });
      }

这样当父级触发事件发射器时,子级接收它并更改其visible 属性。子组件有自己的手动方法将可见属性重置为 false。

从功能的角度来看,它完成了工作:当父组件单击按钮时,组件“出现”。但现在我担心我可能搞砸了他们关系的“连通性”方面。

在编写单元测试时,我目前对组件的了解如下:

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

  const sidebarServiceSpy = jasmine.createSpyObj('SidebarService', [
    'showSidebar'
  ]);

  const fb: FormBuilder = new FormBuilder();

  configureTestSuite(() => {
    TestBed.configureTestingModule({
      imports: [
        MockModule(FormsModule),
        MockModule(ReactiveFormsModule),
        MockModule(TranslateModule.forRoot())
      ],
      declarations: [
        FilterSideBarComponent,
        CheckboxInputComponent,
        MockComponent(CountrySingleSearchComponent),
        MockComponent(UniversitiesSearcherComponent)
      ],
      providers: [
        {provide: SidebarService, useValue: sidebarServiceSpy},
        {provide: FormBuilder, useValue: fb},
      ]
    });
  });

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

  it('should create', () => {
    expect(component).toBeTruthy();
  });
});

到目前为止,唯一编写的测试(“应该创建”)失败了,Jasmine 告诉我: TypeError:无法读取未定义的属性“订阅” 在 在 FilterSideBarComponent.subscribe [as ngOnInit]

我已经在 StackOverflow 中搜索了关于模拟服务订阅方式的类似主题,但我发现的所有示例都使用返回对象、数据或 Observables 的服务。

当然我可以重写服务,只要它保留它的功能,但是 - 有没有一种有效的方法来测试像我这样的“服务”,或者我应该以某种方式重写服务?

【问题讨论】:

    标签: angular jasmine


    【解决方案1】:

    问题是您订阅了未在模拟服务中定义的 toggleSidebar 属性。我不确定 Jasmine 是否支持模拟属性,所以我将创建一个类似于下面的模拟对象。当您想触发您的事件进行测试时,您可以执行 sideBarSubject.next()。

    我也不认为建议在服务中使用 EventEmitters。我也会更改您的服务以使用主题。

    如果您以后需要监视您的新模拟侧边栏服务,您可以执行 spyOn(sidebarServiceSpy, 'showSideBar') 这是必要的,因为您不再将其创建为间谍。

    describe('FilterSidebarComponent', () => {
      let component: FilterSideBarComponent;
      let fixture: ComponentFixture<FilterSideBarComponent>;
    
    
      let sideBarSubject = new Subject<void>();
      const sidebarServiceSpy = {
        toggleSidebar = sideBarSubject;
        showSidebar: Function(){}
      }
    
      const fb: FormBuilder = new FormBuilder();
    
      configureTestSuite(() => {
        TestBed.configureTestingModule({
          imports: [
            MockModule(FormsModule),
            MockModule(ReactiveFormsModule),
            MockModule(TranslateModule.forRoot())
          ],
          declarations: [
            FilterSideBarComponent,
            CheckboxInputComponent,
            MockComponent(CountrySingleSearchComponent),
            MockComponent(UniversitiesSearcherComponent)
          ],
          providers: [
            {provide: SidebarService, useValue: sidebarServiceSpy},
            {provide: FormBuilder, useValue: fb},
          ]
        });
      });
    
      beforeEach(() => {
        fixture = TestBed.createComponent(FilterSideBarComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
      });
    
      it('should create', () => {
        expect(component).toBeTruthy();
      });
    });
    

    【讨论】:

    • 该解决方案不太奏效,但我仍然给它一个“竖起大拇指”,这不仅是因为良好的意图,而且因为你是对的:为此使用 EventEmitter 可能不仅仅是没有推荐,但也有点荒谬。如果我只是想在父组件和子组件之间传递信号,那么使用 Input() 属性对我来说就足够了。但是,对于未来的场合,我会给你的建议(使用 Subjects 而不是 eventEmitters),以防我确实需要从我的服务接收数据或 Observables。谢谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-12-07
    • 2017-08-17
    • 2017-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多