【问题标题】:Jasmine Angular 9 test failing because 'unreachable' stack trace at injectableDefOrInjectorDefFactoryJasmine Angular 9 测试失败,因为 injectableDefOrInjectorDefFactory 的堆栈跟踪“无法访问”
【发布时间】:2020-09-28 13:56:03
【问题描述】:

我在 4 下创建了一个 Angular 应用程序。我已经从一个版本迁移到另一个版本,目前是最新版本 9。我正在审查我的测试。我有一个登录组件,我有 3 个工作测试,现在都失败了。它现在返回以下内容:

LoginComponent should be created ...
Failed: unreachable
Error: unreachable
    at injectableDefOrInjectorDefFactory (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:17302:1)
    at providerToFactory (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:17402:1)
    at providerToRecord (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:17349:1)
    at R3Injector.processProvider (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:17165:1)
    at http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:17144:1
    at http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:1400:1
    at Array.forEach (<anonymous>)
    at deepForEach (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:1400:1)
    at R3Injector.processInjectorType (http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:17140:1)
    at http://localhost:9876/_karma_webpack_/node_modules/@angular/core/__ivy_ngcc__/fesm2015/core.js:16881:1

茉莉花测试如下:

// File: login.component.spec.ts
import { async, ComponentFixture, TestBed, inject, fakeAsync, tick } from '@angular/core/testing';
import { FormsModule, ReactiveFormsModule, NgForm } from '@angular/forms';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { of, throwError } from 'rxjs';
import { SelectItem } from 'primeng/api';
import { Dialog } from 'primeng/dialog';
import { Header, Footer } from 'primeng/api';
import { ButtonModule } from 'primeng/button';
//
import { AlertsService } from '../../global/alerts/alerts.service';
import { UserService } from '../../net-incident/services/user.service';
import { AuthService } from '../../net-incident/services/auth.service';
import { LoginComponent } from './login.component';
import { ServerSelectionWindowComponent } from '../../net-incident/server-selection-window/server-selection-window.component';
//
describe('LoginComponent', () => {
    let sut: LoginComponent;
    let fixture: ComponentFixture<LoginComponent>;
    let alertService: AlertsService;
    const authServiceSpy = jasmine.createSpyObj('AuthService',
            ['authenticate', 'logout', 'isLoggedIn', 'isLoggedOut']);
    const userServiceSpy = jasmine.createSpyObj('UserService',
            ['emptyUser', 'getUser', 'getUserServer']);
    //
    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [
                FormsModule,
                ButtonModule,
                BrowserAnimationsModule
            ],
            declarations: [
                LoginComponent,
                Dialog,
                Header,
                Footer,
                ServerSelectionWindowComponent
            ],
            providers: [
                { provide: AlertsService, useClass: AlertsService },
                { provide: AuthService, useValue: authServiceSpy },
                { provide: UserService, useClass: userServiceSpy }
            ]
        } );
        alertService = TestBed.get( AlertsService );
        TestBed.compileComponents();
    }));
    beforeEach(() => {
        fixture = TestBed.createComponent(LoginComponent);
        sut = fixture.componentInstance;
        fixture.detectChanges();
    });
    it('should be created ...', () => {
        expect( sut ).toBeTruthy();
    });
});

【问题讨论】:

    标签: angular jasmine angular-ivy


    【解决方案1】:

    对我来说,我将 useClass 更改为 useValue。像下面的例子:

    TestBed.configureTestingModule({
          declarations: [...],
          imports: [...],
          providers: [
            { provide: PlansService, useClass: mockPlansService },
            { provide: AuthService, useClass: mockOAuthService }
          ]
        }).compileComponents();
    

    为此

    TestBed.configureTestingModule({
          declarations: [...],
          imports: [...],
          providers: [
            { provide: PlansService, useValue: mockPlansService },
            { provide: AuthService, useValue: mockOAuthService }
          ]
        }).compileComponents();
    

    【讨论】:

    • 有一个令人印象深刻的 68 票赞成的答案。为什么有人可能更喜欢你的方法而不是那种方法?您是否正在利用新功能?是否存在更适合您的方法的场景?解释总是有用,但在这里尤其很重要。
    【解决方案2】:

    您还可以创建一个模拟类用作您的 UserService:

    class MockUserService {
    
      myMethod(): void {
        // mocked logic
      } 
    }
    
    describe('LoginComponent', () => {
    ...
    
    providers: [
        ...
        { provide: UserService, useClass: MockUserService }
    ]
    ...
    
    });
    

    【讨论】:

    • 我曾经使用手工制作的模拟,但我已经转向使用间谍。
    【解决方案3】:
    providers: [
        ...
        { provide: UserService, useClass: userServiceSpy }
    ]
    

    应改为:

    providers: [
        ...
        { provide: UserService, useValue: userServiceSpy }
    ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-30
      相关资源
      最近更新 更多