【问题标题】:ERROR TypeError & ERROR CONTEXT DebugContext_ in Angular Unit test - template produces errorAngular 单元测试中的 ERROR TypeError & ERROR CONTEXT DebugContext_ - 模板产生错误
【发布时间】:2018-06-18 14:31:04
【问题描述】:

我的指令有以下测试。看起来是这样的:

import {Component} from '@angular/core';
import {FormsModule, FormBuilder, ReactiveFormsModule} from '@angular/forms';
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
import {By} from '@angular/platform-browser';
import {TrimInputDirective} from './trim-input.directive';

/**
 * Test Component for Trim
 */
@Component({
  selector: 'my-directive-test-component',
  template: `<form [formGroup]="testResultForm">
                    <input type="text" class="trim-me" formControlName="TrimMe" name="TrimMe">
                      <input type="text" class="msa-trim-ignore" formControlName="TrimIgnore" name="TrimIgnore">
                        <input type="password" formControlName="TrimPassword" name="TrimPassword">
                  </form>`
})
class TestComponent {
  public testResultForm: any;
}


fdescribe('Trim Directive', () => {
  let fixture: ComponentFixture<TestComponent>;
  let component: TestComponent;
  let inputDebugElementTrim: any;
  let inputDebugElementNoTrim: any;
  let inputDebugElementPassword: any;
  const formBuilder: FormBuilder = new FormBuilder();

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [
        TestComponent,
        TrimInputDirective
      ],
      imports: [FormsModule, ReactiveFormsModule],
      providers: [{ provide: FormBuilder, useValue: formBuilder }]
    }).compileComponents().then(() => {
      fixture = TestBed.createComponent(TestComponent);
      component = fixture.componentInstance;
      component.testResultForm = formBuilder.group({
        TrimMe: ['     1234.56     '],
        TrimIgnore: ['     1234.56     '],
        TrimPassword: ['     1234.56     ']
      });
      inputDebugElementTrim = fixture.debugElement.query(By.css('.trim-me')).nativeElement;
      inputDebugElementNoTrim = fixture.debugElement.query(By.css('.msa-trim-ignore')).nativeElement;
      inputDebugElementPassword = fixture.debugElement.query(By.css('input[type=password]')).nativeElement;
    });
  }));

  it('should trim the input', () => {
    inputDebugElementTrim.dispatchEvent(new Event('blur'));
    fixture.detectChanges();
    expect(inputDebugElementTrim.value).toBe('1234.56');
  });

  it('should not trim the input due to ignore class', () => {
    inputDebugElementNoTrim.dispatchEvent(new Event('blur'));
    fixture.detectChanges();
    expect(inputDebugElementNoTrim.value).toBe('     1234.56     ');
  });

  it('should not trim the input due to password input', () => {
    inputDebugElementPassword.dispatchEvent(new Event('blur'));
    fixture.detectChanges();
    expect(inputDebugElementPassword.value).toBe('     1234.56     ');
  });
});

我的测试通过但在控制台中我的模板第一行出现类型错误?控制台显示: ERROR TypeError {...} ERROR CONTEXT DebugContext_ {...} 我无法确定这是为什么?我的指令如下所示:

import { Directive, HostListener, forwardRef } from '@angular/core';
import { DefaultValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export const TRIM_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => TrimInputDirective),
  multi: true
};

/**
 * The trim accessor for writing trimmed value and listening to changes that is
 * used by the {@link NgModel}, {@link FormControlDirective}, and
 * {@link FormControlName} directives.
 */
/* tslint:disable */
@Directive({
  selector: `
    input
    :not([type=checkbox])
    :not([type=radio])
    :not([type=number])
    :not([type=password])
    :not([readonly])
    :not(.msa-trim-ignore)
    :not([useValueAsDecimal])
    [formControlName],

    input
    :not([type=checkbox])
    :not([type=radio])
    :not([type=number])
    :not([type=password])
    :not([readonly])
    :not(.msa-trim-ignore)
    :not([useValueAsDecimal])
    [formControl],

    input
    :not([type=checkbox])
    :not([type=radio])
    :not([type=number])
    :not([type=password])
    :not([readonly])
    :not(.msa-trim-ignore)
    :not([useValueAsDecimal])
    [ngModel],

    textarea
    :not([readonly])
    :not(.msa-trim-ignore)
    [formControlName],

    textarea
    :not([readonly])
    :not(.msa-trim-ignore)
    [formControl],

    textarea
    :not([readonly])
    :not(.msa-trim-ignore)[ngModel],
    :not([readonly])
    :not(.msa-trim-ignore)
    [ngDefaultControl]
  `,
  providers: [ TRIM_VALUE_ACCESSOR ]
})
/* tslint:enable */
export class TrimInputDirective extends DefaultValueAccessor {

  protected _onTouched: any;

  /**
   * ngOnChange - Lifecycle hook that is called when any data-bound property of a directive changes.
   * @param {string} val - trim value onChange.
   */
  @HostListener('input', ['$event.target.value'])
  public ngOnChange = (val: string) => {
    this.onChange(val.trim());
  }

  /**
   * applyTrim - trims the passed value
   * @param {string} val - passed value.
   */
  @HostListener('blur', ['$event.target.value'])
  public applyTrim(val: string) {
    this.writeValue(val.trim());
    this._onTouched();
  }

  /**
   * writeValue - trims the passed value
   * @param {any} value - passed  value.
   */
  public writeValue(value: any): void {
    if (typeof value === 'string') {
      value = value.trim();
    }

    super.writeValue(value);
  }

  /**
   * registerOnTouched Registers a callback function that should be called when the control receives a blur event.
   * @param {function} fn - The user information.
   */
  public registerOnTouched(fn: any): void {
    this._onTouched = fn;
  }
}

我确定我已经导入/提供了我应该做的一切。可悲的是,控制台错误并不能真正帮助我确定为什么会出现此错误?

提前感谢任何建议。

【问题讨论】:

    标签: angular unit-testing jasmine karma-runner


    【解决方案1】:

    我不知道你是怎么看的,但是 chrome 给了我以下错误:

    VM4549 TestComponent.ngfactory.js:25 错误类型错误:this._onTouched 不是函数

    您必须通过调用fixture.detectChanges() 告诉TestBed 执行数据绑定。只有这样您的_onTouched 函数才会被注册。

    beforeEach(() => {
      fixture.detectChanges();
    });
    
    it('should trim the input', () => {
      ...
    });
    ...
    

    【讨论】:

    • 添加fixture.detectChanges();有效,但是控制台没有/没有给我与您看到的相同的错误。无论如何,谢谢!
    【解决方案2】:
    you could try by importing  ComponentFixtureAutoDetect for auto detection change -
    
    import { ComponentFixtureAutoDetect } from '@angular/core/testing'
    
    then you can use it in provider - 
    
    TestBed.configureTestingModule({
      declarations: [ BannerComponent ],
      providers: [
        { provide: ComponentFixtureAutoDetect, useValue: true }
      ]
    });
    
    By this you don't need to call fixture.detectchanges() every time 
    

    【讨论】:

      猜你喜欢
      • 2020-03-12
      • 1970-01-01
      • 2018-08-29
      • 2019-06-16
      • 2011-04-26
      • 2022-07-27
      • 2019-01-22
      • 2021-02-05
      • 1970-01-01
      相关资源
      最近更新 更多