Как мне создать шпиона для конструктора с помощью Jasmine? - PullRequest
0 голосов
/ 26 октября 2018

Я пытаюсь написать свой первый «сложный» тест против Angular, используя Жасмин и Карму.Вот код, против которого я пытаюсь написать тест:

import { Component, Inject } from "@angular/core";
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';
import { Router } from "@angular/router";
import { AuthService } from '../../services/auth.service';

@Component({
   selector: "login",
   templateUrl: "./login.component.html",
   styleUrls: ['./login.component.css']
})

export class LoginComponent {

title: string;
form!: FormGroup;

constructor(private router: Router,
    private frmbuilder: FormBuilder,
    private authService: AuthService,
    @Inject('BASE_URL') private baseUrl: string) {

    this.title = "User Login";

    this.createForm();
}

createForm() {
    this.form = this.frmbuilder.group({
        Email: ['', Validators.required],
        Password: ['', Validators.required]
    });
}…

Я пытаюсь написать тест для метода createForm:

import { TestBed, async } from '@angular/core/testing';
import { LoginComponent } from './login.component';
import { Router } from '@angular/router';
import { AuthService } from '../../services/auth.service';
import { FormGroup, FormControl, FormBuilder, Validators } from '@angular/forms';


describe('create form', () => {

  let component : LoginComponent;
  let service : AuthService;
  let router: Router;
  let frmBuilder: FormBuilder;
  let spy : any;

beforeEach(() => {
    spyOn(component, LoginComponent.arguments(router, frmBuilder, service));
    component = new LoginComponent(router, frmBuilder, service, '');

});


it('expect the login form to have been created', () => {
    expect(component.createForm()).toHaveBeenCalled();
});

});

Когда я запускаюtest Я получаю следующую ошибку: TypeError: свойства 'caller', 'callee' и 'arguments' не могут быть доступны для функций строгого режима или объектов аргументов для вызовов к ним.

Ссылка, предлагаемая какответ не решает мою проблему.Я думаю, это потому, что я вызываю мой метод createForm в конструкторе (совершенно корректно, но сложно проверить).Если я изменю первую строку моего теста в beforeEach на: spyOn(component,'createForm');, тогда я получу ошибку could not find an object to spy upon for createForm()

1 Ответ

0 голосов
/ 26 октября 2018

Для того, чтобы шпионить за методом, вам нужен экземпляр класса (тестируемая система или sut), которому принадлежит метод, так что метод может быть заменен шпионом.

spyOn<any>(sut, 'initializeForm');

Это означает, что рассматриваемый класс должен быть создан до того, как вы будете шпионить за его методами или свойствами, что легко сделать для того, чтобы шпионить за объектами, которые вы передаете конструктору в вашем методе beforeEach, или для методов, принадлежащих к sut, которые вызывается не самим конструктором, а потом.

Но так как вы хотите проверить, вызывает ли конструктор метод, но вам нужен экземпляр этого класса перед вызовом конструктора, чтобы шпионить за методом, который вызывается конструктором, но создавать экземпляр класса без его конструктор невозможен, вы столкнулись с дилеммой .

Мой совет - переместить вызов метода в метод ngOnInit и проверить его.

describe('constructor', () => {
    it('should create the sut', () => {
        expect(sut).toBeDefined();
    });
});

describe('ngOnInit', () => {
    it('should call initializeForm', () => {
        spyOn<any>(sut, 'initializeForm');

        sut.ngOnInit();

        expect(sut.initializeForm).toHaveBeenCalled();
    });
});

describe('initializeForm', () => {
    it('should initialize the form', () => {
        sut.initializeForm();

        expect(sut.form).toBeDefined();
    });
});

Да, простые формы могут быть созданы в вашем конструкторе. Но по мере того, как все усложняется, например, когда вы хотите получить доступ к значениям параметра @Input, метод ngOnInit является лучшим местом для начала создания формы.

Для того, чтобы Angular не выдавал ошибки шаблонов, либо предоставьте скрытую / пустую версию вашей формы в конструкторе, либо удерживайте HTML-код от рендеринга до тех пор, пока ngOnInit не пройдет и форма не будет определена с помощью * ngIf.

<form *ngIf="form" [formGroup]="form">
  ...
</form>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...