【问题标题】:Testing angular form submitting测试角度表单提交
【发布时间】:2018-10-26 10:02:54
【问题描述】:

我正在测试一个 Angular 应用程序,尤其是这个 HTML 输入:

<form  name="editForm" role="form" novalidate (ngSubmit)="save()" #editForm="ngForm">
     <input type="text" name="nombre" id="field_nombre"
    	                [(ngModel)]="paciente.nombre" required/>
(etc. f.e. button on submit...)
这是我的组件:

imports....


export class PacienteDialogComponent implements OnInit {
    
    paciente: Paciente;
    
    ....
    
       save() {
        this.isSaving = true;
        if (this.paciente.id !== undefined) {
            this.subscribeToSaveResponse(
                this.pacienteService.update(this.paciente));
        } else {
            this.subscribeToSaveResponse(
                this.pacienteService.create(this.paciente));
        }
    }
}
这是我的 patient.model.ts

export class Paciente implements BaseEntity {
    constructor(
        public id?: number,
        public nombre?: string,
        public sexo?: Sexo,
        
        .....
我想测试表单,这意味着在提交时它确实在调用 save() 函数。 我的测试中有这个:

describe('Paciente Management Dialog Component', () => {
        let comp: PacienteDialogComponent;
        let fixture: ComponentFixture<PacienteDialogComponent>;
        let debugElement: DebugElement; //create a debgElement for testing

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

  beforeEach(() => {
            fixture = TestBed.createComponent(PacienteDialogComponent);
            comp = fixture.componentInstance;
            debugElement = fixture.debugElement;
        });
                //a default generated test which controls if the save method really saves a new patient with its name, id, sex, etc.
        it('Should call create service on save for new entity',
           inject([],
               fakeAsync(() => {
                   // GIVEN
                   const entity = new Paciente();
                   spyOn(service, 'create').and.returnValue(Observable.of(new HttpResponse({body: entity})));
                   comp.paciente = entity;
                   // WHEN
                   comp.save();
                   tick(); // simulate async

                   // THEN
                   expect(service.create).toHaveBeenCalledWith(entity);
                   expect(comp.isSaving).toEqual(false);
                   expect(mockEventManager.broadcastSpy).toHaveBeenCalledWith({ name: 'pacienteListModification', content: 'OK'});
                   expect(mockActiveModal.dismissSpy).toHaveBeenCalled();
               })
           )
       );
// And teh second thing I want to test is if ngSubmit is really calling the save() function


           it ('should call the onSubmit method', async(() => {
            //fixture.detectChanges();
            spyOn(comp,'save');
            var1 = debugElement.query(By.css('button')).nativeElement;
            console.log('print button ' + var1);
            var1.click();
            expect(comp.save).toHaveBeenCalledTimes(0);//verify...
            }));

//And also if isSaving is set to true


 it ('should set isSaving to true', async(() => {
           comp.save();
            expect(comp.isSaving).toBeTruthy();
         
           }));





         
        
        

1.现在我有这些问题:第一个测试是默认生成的,不是我写的。在这一行 const entity = new Paciente(); 我应该调用 Paciente 的参数吗?像 id、sex、name 或者默认这样不带参数。第一个测试的目的是检查 save() 函数是否真的保存了患者及其 id、sex 等数据。

2.对于第二个测试,我在 Angular 教程中读到:HaveBennCalled(0) 是测试该间谍是否被调用以及调用多少次的正确方法。但无论如何,它是否真的测试按钮是否调用函数 save()。我认为它只检查按钮之前是否没有被调用过,而不是现在是否在保存函数中调用它。

3.这 3 项测试是否足以完成表单提交?

【问题讨论】:

  • @tricheriche 这是一个棘手的问题
  • 一点也不难:你的测试没用。您创建一个值,将此值设置为您的输入,并期望该输入的绑定具有所述值。这不是你应该做的测试,你只是在测试 Angular 是否在这里工作。您应该测试您的代码是否有效,而不是库是否有效。
  • 这样想你的测试:如果用户...会发生什么?。例如,如果用户没有在这个输入中输入任何值会发生什么?这就是你应该测试的:当你提交表单时,这个值不为空。
  • 这是下一步。首先考虑用户放置的值是否不是 paciente.nombre 而是其他东西。 我不需要首先测试绑定吗?无论如何输出的错误不应该存在,因为 paciente.nombre 不是未定义的
  • 怎么可能是别的东西?您的绑定在paciente.nombre,并且是硬编码的。如果您想测试输入的值是否正确,您将进行端到端测试,而不是单元测试。在这里,您只需要测试您的应用程序是否按预期运行,而不是用户输入的格式是否正确。因为如果这样做,您将重复您的测试(单元 + e2e)。

标签: javascript html angular forms properties


【解决方案1】:

按照我的 cmets,这里是如何测试表单是否正确提交。

假设你有一个接口Patient

export interface Patient {
  id: number;
  name: string;
}

在你的组件中,你有一个表单,你通过submit()提交它:

submit() {
  this.patientService.savePatient(this.patient).subscribe(result => {
    console.log('Patient created');
  });
}

现在您的服务发出 HTTP 调用并检查字段是否正常:

savePatient(patient: Patient): Observable<any> {
  if (typeof patient.id !== number) { return Observable.throw('ID is not a number'); }
  if (typeof patient.name !== string) { return Observable.throw('Name is not a string'); }

  return this.http.post<any>(this.url, patient);
}

那么你的测试应该是这样的。一、组件:

it('Should call the service to save the patient in DB', () => {
  // Spy on service call
  // Expect spy to have been called
});

it('Should log a message on success', () => {
  // Spy on console log
  // Expect console log to have been called with a string
});

也可以测试错误处理是否正确,是否有错误码等

现在在服务中:

it('Should throw an error if the ID is not a number', () => {
  // Mock a patient with a string ID
  // Expect an error to be thrown
});

// Same thing for the name, you get the idea

it('Should make an HTTP call with a valid patient', () => {
  // Spy on the HttpTestingController
  // Expect the correct endpoint to have been called, with the patient as the payload
});

这些测试的总体思路是涵盖任何可能发生的情况。这将允许您防止副作用:例如,如果有一天您决定将您的 ID 传递给字符串,单元测试将失败并告诉您

你希望我发送一个字符串,但我只传递一个数字

这是单元测试的目的。

【讨论】:

  • 非常感谢。但是我需要把我的问题具体化一点,这样每个人都可以清楚地了解如何测试在 anular 上提交的表单。
  • 你应该提出一个新问题,这太模糊了,人们不会理解。
  • 如果ID不是数字,你能具体化验证测试吗?或者看看这个问题stackoverflow.com/questions/50524398/…
猜你喜欢
  • 1970-01-01
  • 2015-04-29
  • 2018-09-15
  • 2018-05-03
  • 2015-07-03
  • 2018-10-22
  • 2016-12-19
  • 2014-06-28
  • 1970-01-01
相关资源
最近更新 更多