【问题标题】:Expected null to be truthy. Jasmine / Karma预期 null 是真实的。茉莉花 / 业力
【发布时间】:2018-11-14 18:05:35
【问题描述】:

我正在尝试测试注入到我创建的模拟类中的组件。虽然当我尝试测试它的存在时该组件有效,但它返回 null。

可注射成分:

import { Injectable, ElementRef, Renderer2, RendererFactory2 } from '@angular/core';

@Injectable()
export class NgBackdropComponent {
  private renderer: Renderer2;
  private appElementRef: ElementRef;

  message: string = 'Carregando...';

  constructor(rendererFactory: RendererFactory2) {
    this.renderer = rendererFactory.createRenderer(null, null);
    this.appElementRef = new ElementRef(<Element>document.getElementsByTagName('body').item(0));
  }

  show() {
    const divSpinnerItem1 = this.renderer.createElement('i');
    const divSpinnerItem2 = this.renderer.createElement('i');
    const divSpinnerItem3 = this.renderer.createElement('i');
    const divSpinner = this.renderer.createElement('div');
    this.renderer.addClass(divSpinner, 'spinner');
    this.renderer.appendChild(divSpinner, divSpinnerItem1);
    this.renderer.appendChild(divSpinner, divSpinnerItem2);
    this.renderer.appendChild(divSpinner, divSpinnerItem3);

    const spanMensagem = this.renderer.createElement('span');
    spanMensagem.innerHTML = this.message;

    const div = this.renderer.createElement('div');
    this.renderer.addClass(div, 'lock-content');
    this.renderer.appendChild(div, divSpinner);
    this.renderer.appendChild(div, spanMensagem);

    this.renderer.appendChild(this.appElementRef.nativeElement, div);
  }

  hide() {
    const elemento = this.appElementRef.nativeElement.querySelector('.lock-content');
    if (elemento) {
      elemento.remove();
    }
  }
}

我的测试环境:

import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { NgBackdropComponent } from './ng-backdrop.component';
import { Component } from '@angular/core';
import { By } from '@angular/platform-browser';


@Component({
  template: `
    <button (click)="clickButton()"></button>
    `
})
class MockNgBackdropComponent {
  constructor(private backdrop: NgBackdropComponent) { }

  clickButton() {
    this.backdrop.message = 'Teste BackDrop aesdas';
    this.backdrop.show();
    console.log('iniciei backdrop');
  }

  closeBackdrop() {
    this.backdrop.hide();
  }
}

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

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [MockNgBackdropComponent],
      providers: [NgBackdropComponent]
    })
      .compileComponents();
  }));

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

  describe('Deve injetar', async () => {

    it('Deve ter uma div principal', function () {
      const btnClick = fixture.nativeElement.querySelector('button');
      btnClick.click();
      fixture.detectChanges();

      const el = fixture.nativeElement.querySelector('.lock-content');
      console.log(el);

      expect(el).toBeTruthy();
    });
  });
});

在测试中,我创建了一个 Mock 类,并在其中注入了我的组件。 我不明白为什么它找不到类,因为它存在。

【问题讨论】:

    标签: jasmine angular6 karma-jasmine


    【解决方案1】:

    在组件中找不到它的原因是因为你没有在组件中创建它。如果您在构造函数中查看这一行:

    this.appElementRef = new ElementRef(<Element>document.getElementsByTagName('body').item(0))
    

    您是在文档上直接在&lt;body&gt; 元素中创建它。如果你在你的规范中搜索它,你会在那里找到它。我创建了一个STACKBLITZ 来向您展示我的意思。以下是来自 stackblitz 的规范:

    it('Deve ter uma div principal', () => {
      const btnClick = fixture.nativeElement.querySelector('button');
      console.log(btnClick);
      btnClick.click();
      fixture.detectChanges();
      const appElementRef = new ElementRef(<Element>document.getElementsByTagName('body').item(0));
      const el = appElementRef.nativeElement.querySelector('.lock-content');
      expect(el).toBeTruthy();
    });
    

    补充一点说明:

    如果你console.log(appElementRef) 你会注意到它的tagName 是body,并注意它的nativeElement.innerHTML 的内容这看起来像“漂亮”:

    <body>
        <div class="jasmine_html-reporter">
            <div class="jasmine-banner"><a class="jasmine-title" href="http://jasmine.github.io/" target="_blank"></a><span
                    class="jasmine-version">3.3.0</span></div>
            <ul class="jasmine-symbol-summary"></ul>
            <div class="jasmine-alert"></div>
            <div class="jasmine-results">
                <div class="jasmine-failures"></div>
            </div>
        </div>
        <div id="nprogress" style="transition: none 0s ease 0s; opacity: 1;">
            <div class="bar" role="bar" style="transform: translate3d(0%, 0px, 0px); transition: all 200ms ease 0s;">
                <div class="peg"></div>
            </div>
        </div>
        <div id="root0" ng-version="7.0.1">
            <button></button>
        </div>
        <div class="lock-content">
            <div class="spinner">
                <i></i>
                <i></i>
                <i></i>
            </div>
            <span>Teste BackDrop aesdas</span>
        </div>
    </body>
    

    注意按钮是如何在带有id="root0" 的div 中创建的?但是,class="lock-content" 的 div 是在根 &lt;body&gt; 元素上创建的,因此不在组件的 div 内。

    其实你console.log(fixture.nativeElement)可以看得很清楚,看到tagName是“div”,它的innerHTML是&lt;button&gt;&lt;/button&gt;,它有两个属性:id: "root0"ng-version: "7.0.1"。把它们放在一起,它看起来像这样:

    <div id="root0" ng-version="7.0.1">
        <button></button>
    </div>
    

    所以你可以清楚的看到你在组件中创建的div是找不到的,因为你是在组件外创建的。

    我希望这会有所帮助。

    【讨论】:

    • 乐于助人。 :)
    【解决方案2】:

    我认为你应该使用DebugElement,例如:

    it('Deve ter uma div principal', function () {
      const btnClick = fixture.debugElement.query(By.css('button'));
      btnClick.click();
      fixture.detectChanges();
    
      const el = fixture.debugElement.query(By.css('.lock-content'));
      console.log(el);
    
      expect(el).toBeTruthy();
    });
    

    关注this link 了解更多信息。

    【讨论】:

      猜你喜欢
      • 2014-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-15
      • 1970-01-01
      • 2016-08-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多