我指的是Plunker,它演示了Angular 2/4中的单元测试表单提交 . 如果我正确理解了代码,那么测试会验证表单是否正确提交,并且最终(通过 Spy )提交的内容会调用 this.formSubmit.emit(); .

为什么't the test validate that the component'的 doFormSubmit 方法也被称为?

我希望测试(和我自己的表单测试)验证(以相同的期望)表单提交和组件方法 .

我看到其他人的测试,直接组件的方法测试没有形式正确调用和我看到这样的测试得到正确的最终结果,但没有验证所谓的确切方法 . 但我没有看到任何两种测试 .

是否有一些async / fakeasync / tick问题,我没有看到会阻止该测试?

<form #form="ngForm" (ngSubmit)="doFormSubmit()">
  <div>
    <div class="clearfix m-b-1">
      <label class="form-control-static" for="reviewContent" i18n>l.product.show.reviewForm.content</label>
      <div>
        <textarea
          class="form-control"
          id="reviewContent"
          name="content"
          required
          [(ngModel)]="model.content"
          #content="ngModel"
        ></textarea> {{model.content}}
      </div>
    </div>

  </div>
  <div>
    <div class="clearfix m-b-1">
      <label class="form-control-static" for="reviewRating" i18n>l.product.show.reviewForm.rating</label>
      <div>
        <input
          type="number"
          class="form-control l-number-input"
          id="reviewRating"
          name="rating"
          required
          [(ngModel)]="model.rating"
          #rating="ngModel"
        />{{model.rating}}
      </div>
    </div>

  </div>
  <div>
    <button
      type="submit"
      class="btn btn-primary btn-lg btn-block"
      [disabled]="!form.form.valid"
      i18n
    >l.product.show.reviewForm.submit</button>
  </div>
</form>
{{doFormSubmitCalled}}
import { Component, Input, ViewChild, Output, EventEmitter } from '@angular/core';
import { NgForm } from '@angular/forms'

@Component({
  selector: 'home-comp',
  templateUrl: `app/test.component.html`
})
export class TestComponent {
  @Input()
  public model: any;
  doFormSubmitCalled = false;

  @Output()
  public formSubmit = new EventEmitter<any>();

  public doFormSubmit() {
    //alert.log("doFormSubmit called");
    this.formSubmit.emit();
    this.doFormSubmitCalled = true;
  }
}
import { FormsModule } from '@angular/forms';
import { DebugElement } from '@angular/core';
import { By } from '@angular/platform-browser';

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

import { TestComponent } from './test.component';

function newEvent(eventName: string, bubbles = false, cancelable = false) {
    let evt = document.createEvent('CustomEvent');  // MUST be 'CustomEvent'
    evt.initCustomEvent(eventName, bubbles, cancelable, null);
    return evt;
}

describe('ProductShowReviewFormComponent', () => {
    let fixture: ComponentFixture<TestComponent>;
    let comp: TestComponent;
    let submitSpy: jasmine.Spy;

    // SO: spy on component's method
    let componentMethodSpy: jasmine.Spy;

    let contentInput: HTMLTextAreaElement;
    let ratingInput: HTMLInputElement;
    let form: DebugElement;

    beforeEach(async(() => {
        TestBed
            .configureTestingModule({
                imports: [FormsModule],
                declarations: [TestComponent],
            })
            .compileComponents()
            ;
    }));

    beforeEach(fakeAsync(() => {
        fixture = TestBed.createComponent(TestComponent);
        comp = fixture.componentInstance;
        submitSpy = spyOn(comp.formSubmit, 'emit');

        contentInput = fixture.debugElement.query(By.css('#reviewContent')).nativeElement;
        ratingInput = fixture.debugElement.query(By.css('#reviewRating')).nativeElement;
        form = fixture.debugElement.query(By.css('form'));

        // SO: component's method spy - EDIT: MUST CALL THROUGH
        componentMethodSpy = spyOn(component, 'doFormSubmit').and.callThrough();

        comp.model = { content: '', rating: '' };

        fixture.detectChanges();
        tick();
    }));

    it('should modify message', fakeAsync(() => {
        const expectedContent = 'The longest content.';
        const expectedRating = '4';

        contentInput.value = expectedContent;
        contentInput.dispatchEvent(newEvent('input'));

        ratingInput.value = expectedRating;
        ratingInput.dispatchEvent(newEvent('input'));

        fixture.detectChanges();
        tick();

        form.triggerEventHandler('submit', null);

        expect(submitSpy.calls.any()).toBe(true);
        expect(comp.model.content).toBe(expectedContent);
        expect(comp.model.rating.toString()).toBe(expectedRating);

        // SO: was the Component's method called
        expect(componentMethodSpy).toHaveBeenCalled();
    }));
});