茉莉花测试错误:预期的间谍已被召唤

时间:2019-10-22 10:18:30

标签: angular jasmine

我正在尝试编写一个单元测试,以检查在angular 8应用程序中是否调用了组件的onConfirm方法。我目前遇到错误

Error: Expected spy onConfirm to have been called.

我已经试图监视onConfirm,所以不确定为什么我收到上述错误消息。我已经共享了所有可能的代码来帮助诊断问题

单元测试

describe('SettlementAccountsComponent', () => {
    let component: SettlementAccountsComponent;
    let fixture: ComponentFixture<SettlementAccountsComponent>;
    let alertService: AlertService;
    let clientService: ClientService;
    let confirmModal: ConfirmModalComponent;
    class MockClientService {
        getNumberOfTradesWhereOPIIsSetOn(clientCompanyOpiId: number) {
           // return of(this.getNumberOfTradesWhereOPIIsSetOn);
        }

        deleteSettlementAccount(clientCompanyOpiId: number, authUserId: number) {
           // return of(this.deleteSettlementAccount)
        }
    }
    @Component({
        selector: 'settlement-accounts'
    })
    class MockConfirmModalComponent{
        openModal(title: string, message: string, data: any) {}
        closeModal() { }
        ngOnInit() {
        }
        ngAfterViewInit() {
        }
        public Confirm() {
        }
    }
    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [
                HttpClientModule,
                RouterTestingModule,
                FormsModule,
                TranslateModule.forRoot({
                    loader: {
                        provide: TranslateLoader,
                        useClass: TranslateLanguageLoader
                    }
                })
            ],
            declarations: [
                SettlementAccountsComponent,
                AccountEditorModalComponent,
                SetDefaultComponent,
                ModalDirective
            ],
            providers: [
                AuthService,
                AlertService,
                ConfigurationService,
                LocalStoreManager,
                AppTitleService,
                AppTranslationService,
                NotificationService,
                NotificationEndpoint,
                EndpointFactory,
                ClientEndpoint,
                [{ provide: ClientService, useClass: MockClientService }],
                [{ provide: ConfirmModalComponent, useClass: MockConfirmModalComponent }]
            ],
            schemas: [NO_ERRORS_SCHEMA]
        })
            .compileComponents();
    }));
    beforeEach(() => {
        //This gives default constructor
                //use this if constructor calls other methods especially private
        function getMockInstance(classToMock: any) {
            // Save current class prototype
            var oldPrototype = classToMock.prototype;
            // Create empty type and copy the saved prototype
            var newClass = function () {
                return;
            };
            newClass.prototype = oldPrototype;
            // Create a mock of the new class (empty constructor with same functions as classToMock)
            var newInstance = new newClass();
            return TypeMoq.Mock.ofInstance(newInstance);
        }
        const authServiceMock: TypeMoq.IMock<AuthService> = getMockInstance(AuthService);
        authServiceMock.setup(x => x.currentUser)
            .returns(() =>
            new User('42', 'Chuck Norris', null, null, null, null, 1, null, null, null, null));

        const localStoreMock: TypeMoq.IMock<LocalStoreManager> = TypeMoq.Mock.ofType(LocalStoreManager);
        // localStoreMock.setup(x => x.getInitEvent())
        //     .returns(() => Observable.pipe(of()));
        clientService = TestBed.get(ClientService);
        confirmModal = TestBed.get(ConfirmModalComponent);
        component = new SettlementAccountsComponent(
              alertService
            , clientService
            , authServiceMock.object)
    });

 fit('onConfirm should be called', () => {
       let clientCompanyOpiId = 10;

       let testConfirmModal = ({
        title: 'Delete Settlement Account',
        message: 'Are you sure you want to delete this OPI account?'
       } as ConfirmModalComponent);
       component.confirmModal = testConfirmModal;

       accounts: SettlementAccountModel[0];

       this.accounts = [110,1796,15,'GBP'];

       component.accounts = this.accounts;    
       component.accounts.length = 1;

       spyOn(component, 'removeSettlementConfirmation').and.returnValue("mock response");
       spyOn(clientService, 'getNumberOfTradesWhereOPIIsSetOn').and.returnValue("test");
       spyOn(clientService, 'deleteSettlementAccount').and.callThrough();
       spyOn(component, 'onConfirm').and.callThrough();
       //component.onConfirm(clientCompanyOpiId);
       expect(component.onConfirm).toHaveBeenCalled();
       //expect(component.confirmModal).toBeTruthy();
    });

确认模式

import { Component, OnInit, AfterViewInit, ViewChild, Injectable, EventEmitter, Output } from '@angular/core';
import { AlertService } from '../../../services/alert.service';
import { ModalDirective } from 'ngx-bootstrap/modal';

@Component({
    selector: 'app-confirm-modal',
    templateUrl: './confirm-modal.component.html'
})

@Injectable()
export class ConfirmModalComponent implements OnInit, AfterViewInit {
    public title: string;
    public message: string;

    public data: any;
    public isLoading: boolean;

    @Output() onConfirm: EventEmitter<any> = new EventEmitter();

    @ViewChild('confirmModal' , {static: false})
    confirmModal: ModalDirective;

    constructor(private alertService: AlertService) {
    }

    ngOnInit() {
        this.alertService.resetStickyMessage();
    }

    ngAfterViewInit() {
        this.confirmModal.hide();
    }

    public openModal(title: string, message: string, data: any) {
        this.title = title;
        this.message = message;
        this.data = data;
        this.confirmModal.show();
    }

    public Confirm() {
        this.onConfirm.emit(this.data);
    }

    public closeModal() {
        this.confirmModal.hide();
    }

}   

SettlementAccountComponent

import { Component, ViewChild, OnInit } from "@angular/core";
import { AlertService, MessageSeverity } from '../../services/alert.service';
import { ClientService } from '../../services/client/client.service';
import { AuthService } from '../../services/auth.service';
import { ClientCompanyVM, ClientCompanyAccountVM } from '../../models/client/client.models';
import { AccountEditorModalComponent } from './account-editor/account-editor-modal.component';
import { ModalDirective } from 'ngx-bootstrap/modal';
import { SettlementAccountModel } from "../../models/client/settlement-account.model";
import { SetDefaultComponent } from "./set-default/set-default.component";
import { ConfirmModalComponent } from "../shared/confirm-modal/confirm-modal.component";
@Component({
    selector: 'settlement-accounts',
    templateUrl: './settlement-accounts.component.html',
    styleUrls: ['./settlement-accounts.component.css']
})
export class SettlementAccountsComponent implements OnInit {
    clientCompany: ClientCompanyVM;
    accounts: SettlementAccountModel[];

    constructor(private alertService: AlertService
        , private clientService: ClientService
        , private authService: AuthService) {
        this.clientCompany = new ClientCompanyVM();
    }
    @ViewChild(AccountEditorModalComponent , {static: false})
    editorModal: AccountEditorModalComponent;
    @ViewChild(SetDefaultComponent , {static: false})
    setDefaultModal: SetDefaultComponent;
    @ViewChild(ConfirmModalComponent, { static: false })
    confirmModal: ConfirmModalComponent;
    ngOnInit() {
        this.alertService.resetStickyMessage();
        this.clientService.getClientCompany(this.authService.currentUser.clientCompanyId)
            .subscribe(
            data => {
                    this.clientCompany = data;
            },
            error => {
                this.alertService.showMessage("Error", "Unable to get Client Company Name", MessageSeverity.error)
            });
        this.getClientCompanyAccounts();
    }
    private getClientCompanyAccounts() {
        this.clientService.getClientCompanyAccounts(this.authService.currentUser.clientCompanyId)
            .subscribe(
            data => {
                    this.accounts = data;
            },
            error => {
                this.alertService.showMessage("Error", "Unable to get Client Company Accounts", MessageSeverity.error)
                });
    }
    onAccountSubmitted() {
        this.getClientCompanyAccounts();
    }
    onAccountSetDefault() {
        this.getClientCompanyAccounts();
    }
    newAccountBoxDisplay() {
        this.editorModal.newAccountBox();
    }
    editAccountBoxDisplay(id: number) {
        this.editorModal.editAccountBox(id);
    }
    preventClick(event) {
        event.preventDefault();
    }
    removeSettlementConfirmation(clientCompanyOpiId: number): void {
        this.clientService.getNumberOfTradesWhereOPIIsSetOn(clientCompanyOpiId)
            .subscribe(
                data => {
                    const assignedTrades = data;
                    const trades = +assignedTrades > 1 ? 's' : '';
                    const message = assignedTrades
                        ? `This OPI account is set on ${assignedTrades} trade${trades}. Are you sure you want to delete it?`
                        : `Are you sure you want to delete this OPI account?`;
                    const title = `Delete Settlement Account`;
                    this.confirmModal.openModal(title, message, clientCompanyOpiId);
                },
                error => {
                    this.alertService.showMessage("Error", "Unable to get Associated Trades for Settlement Account", MessageSeverity.error);
                });
    }
    onConfirm(clientCompanyOpiId: number) {
        if (this.accounts.length > 0 && clientCompanyOpiId) {
            this.clientService.deleteSettlementAccount(clientCompanyOpiId, this.authService.currentUser.authUserId)
                .subscribe(
                    data => {
                        const accountId = this.accounts.indexOf(this.accounts.find(obj => obj.clientCompanyOpiId === clientCompanyOpiId));
                        this.accounts.splice(accountId, 1);
                    },
                    error => {
                        this.alertService.showMessage("Error", "Unable to delete Settlement Account", MessageSeverity.error);
                    });
        }
        this.confirmModal.closeModal();
    }
}

1 个答案:

答案 0 :(得分:0)

您的测试已设置了Spy,但未调用函数。

点击按钮(大概有一个确认按钮),测试应该通过。

或者您可以添加

component.onConfirm(42);

直到测试结束,这也应该起作用

  • 问Google为什么42? (可以是任何数字...)