1

因此,我试图根据 observable 是否发出某些值来测试 HTML。我有服务的初始设置以使 observable 发出正确的值,但是当我去创建另一个测试以测试如果我传递错误数据会发生什么时,我无法更改 observable 发出的值。我觉得我错过了一些小东西,有人可以看看,让我知道我做错了什么吗?

这是规格文件

describe('AlertsComponent', () => {
  let component: AlertsComponent;
  let fixture: ComponentFixture<AlertsComponent>;
  let alertService: any;

  let testAlertGood: Alert = {
    type: AlertType.Success,
    title: 'Test title',
    message: 'Test message',
    forceAction: false
  };

  let testAlertBad: String = 'bad alert';

  let testAlertNoTitle: Alert = {
    type: AlertType.Success,
    title: null,
    message: 'Test message',
    forceAction: false
  };

  beforeEach(async(() => {
    alertService = jasmine.createSpy('AlertService');
    alertService.alert$ = cold('a', { a: testAlertGood });

    TestBed.configureTestingModule({
      declarations: [ AlertsComponent ],
      schemas: [ NO_ERRORS_SCHEMA ],
      providers: [
        {
          provide: Router,
          useClass: class { navigate = jasmine.createSpy('navigate'); }
        },
        {
          provide: AlertService,
          useValue: alertService
        }
      ]
    })
    .compileComponents();
  }));

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

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

  it('should display an alert if the alert$ observable has an Alert value', async () => {
    fixture.detectChanges();
    getTestScheduler().flush();
    fixture.detectChanges();

    const alertElements = fixture.debugElement.queryAll(By.css('.alert-container'));
    const alertIconContainer = fixture.debugElement.query(By.css('.icon-container'));
    const alertIconClass = fixture.debugElement.query(By.css('#alert-icon'));
    const alertTitle = fixture.debugElement.query(By.css('.title'));
    const alertBody = fixture.debugElement.query(By.css('.body'));

    expect(alertElements.length).toBe(1);
    expect(alertIconContainer.nativeElement.getAttribute('class')).toContain('bg-success');
    expect(alertIconClass.nativeElement.getAttribute('class')).toContain('fa-check-circle');
    expect(alertTitle.nativeElement.innerText).toContain('Test title');
    expect(alertBody.nativeElement.innerText).toContain('Test message');
  });

  it('should hide the title p tag if the Alert.title is null', async () => {
    alertService.alert$ = cold('a', { a: testAlertNoTitle });

    fixture.detectChanges();
    getTestScheduler().flush();
    fixture.detectChanges();

    const alertTitle = fixture.debugElement.query(By.css('.title'));
    expect(alertTitle).toBeNull();
  });
});

所以基本上在文件的顶部,我有三个版本的值,当可观察对象发出时我需要测试它们,我只能测试第一个。should display an alert if the alert$测试通过就好了,但它是最后一个失败的测试should hide the title...,因为当我这样做时它似乎并没有改变可观察的alertService.alert$ = cold('a', { a: testAlertNoTitle });

4

1 回答 1

1

你在这里不需要茉莉花大理石。该包在测试多个可观察对象的交互时很有用,而您显然只有一个。对我来说,弹珠在这里看起来有点矫枉过正。

最后一个 it() 的问题是,在组件订阅了初始值之后,您将 alertService.alert$ 的值替换为另一个 observable。这就是发生的事情。

  1. 在 beforeEach 中创建了间谍服务,并且将 cold('a', { a: testAlertGood }) 分配给了 alert$。
  2. 在 beforeEach 中创建组件。我相信它在 ngOnInit() 或通过异步管道订阅 alert$。
  3. 组件从 observable 中获取 testAlertGood。
  4. it() 启动并将cold('a', { a: testAlertNoTitle }) 分配给alert$。它不会改变任何事情,因为 2 和 3 已经发生了。

我建议在这里使用一个好的旧主题而不是弹珠。所以你不需要改变 observable,但是你改变它的发射值。像这样的东西:

describe('AlertsComponent', () => {
    let component: AlertsComponent;
    let fixture: ComponentFixture<AlertsComponent>;
    let alertService: any;

    let testAlertGood: Alert = {
        type: AlertType.Success,
        title: 'Test title',
        message: 'Test message',
        forceAction: false
    };

    let testAlertBad: String = 'bad alert';

    let testAlertNoTitle: Alert = {
        type: AlertType.Success,
        title: null,
        message: 'Test message',
        forceAction: false
    };
    
    const alertSubj = new Subject<any>();

    beforeEach(async(() => {
        alertService = jasmine.createSpy('AlertService');
        alertService.alert$ = alertSubj.asObservable();

        TestBed.configureTestingModule({
            declarations: [ AlertsComponent ],
            schemas: [ NO_ERRORS_SCHEMA ],
            providers: [
                {
                    provide: Router,
                    useClass: class { navigate = jasmine.createSpy('navigate'); }
                },
                {
                    provide: AlertService,
                    useValue: alertService
                }
            ]
        })
            .compileComponents();
    }));

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

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

    it('should display an alert if the alert$ observable has an Alert value', async () => {
        alertSubj.next(testAlertGood);
        
        fixture.detectChanges();
        getTestScheduler().flush();
        fixture.detectChanges();

        const alertElements = fixture.debugElement.queryAll(By.css('.alert-container'));
        const alertIconContainer = fixture.debugElement.query(By.css('.icon-container'));
        const alertIconClass = fixture.debugElement.query(By.css('#alert-icon'));
        const alertTitle = fixture.debugElement.query(By.css('.title'));
        const alertBody = fixture.debugElement.query(By.css('.body'));

        expect(alertElements.length).toBe(1);
        expect(alertIconContainer.nativeElement.getAttribute('class')).toContain('bg-success');
        expect(alertIconClass.nativeElement.getAttribute('class')).toContain('fa-check-circle');
        expect(alertTitle.nativeElement.innerText).toContain('Test title');
        expect(alertBody.nativeElement.innerText).toContain('Test message');
    });

    it('should hide the title p tag if the Alert.title is null', async () => {
        alertSubj.next(testAlertNoTitle);

        fixture.detectChanges();
        getTestScheduler().flush();
        fixture.detectChanges();

        const alertTitle = fixture.debugElement.query(By.css('.title'));
        expect(alertTitle).toBeNull();
    });
});
于 2019-11-05T09:43:51.377 回答