How to reuse all imports in Angular test files

前端 未结 2 1974
情歌与酒
情歌与酒 2020-12-18 03:38

Lets say I have a simple module AppModule which has many imports, declarations and providers. Now I want to write a test for a component ListComponent

相关标签:
2条回答
  • 2020-12-18 03:55

    You can avoid providing long list of nested services and dependencies by created a global TestBed.

    While creating constant arrays for providers and imports is one way to go about this, I wanted to take this to the next step and configure the TestBed on a global level to avoid importing repetitive modules.

    In order to configure a global TestBed I created a common testing module which has the utility method to configure the testing bed. This method can then be reused across all the spec files.

    public static setUpTestBed = (TestingComponent: any) => {
        beforeEach(() => {
          TestBed.configureTestingModule({
            imports: [
              ReactiveFormsModule,
              ...
            ],
            providers: [
              ...
            ],
            declarations: [TestingComponent],
            schemas: [CUSTOM_ELEMENTS_SCHEMA]
          });
        });
      }
    

    CommonTestingModule: Contains utility method for creating the testing bed.
    LoginComponent: login.component.spec.ts -> references to the utility method

    CommonTestingModule.setUpTestBed(LoginComponent);
    

    The full component is given below for reference:

    CommonTestingModule:

    import { ChangeDetectionStrategy, CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
    import { DatePipe } from '@angular/common';
    import { FormsModule, ReactiveFormsModule } from '@angular/forms';
    import { HttpClientTestingModule } from '@angular/common/http/testing';
    import { RouterTestingModule } from '@angular/router/testing';
    import { UtilityService } from '../services/utility.service';
    import { TestBed } from '@angular/core/testing';
    
    @NgModule({
      declarations: []
    })
    export class CommonTestingModule {
    
      public static setUpTestBed = (TestingComponent: any) => {
        beforeEach(() => {
          TestBed.configureTestingModule({
            imports: [
              ReactiveFormsModule,
              FormsModule,
              HttpClientTestingModule,
              RouterTestingModule,
              ... //other imports
            ],
            providers: [
              DatePipe,
              UtilityService,
              ... //other imports
            ],
            declarations: [TestingComponent],
            schemas: [CUSTOM_ELEMENTS_SCHEMA]
          });
        });
      }
    }
    

    And then in all your component spec files you can now reference to the utility method CommonTestingModule.setUpTestBed() which accepts the calling component name as the input parameter.

    login.component.spec.ts

    import { ComponentFixture, TestBed } from '@angular/core/testing';
    import { LoginComponent } from './login.component';
    import { CommonTestingModule } from 'src/app/testing/common-testing.module';
    
    describe('LoginComponent', () => {
      let component: LoginComponent;
      let fixture: ComponentFixture<LoginComponent>;
    
      CommonTestingModule.setUpTestBed(LoginComponent);
    
      beforeEach(() => {
        // create component and test fixture
        fixture = TestBed.createComponent(LoginComponent);
        // get test component from the fixture
        component = fixture.componentInstance;
        component.ngOnInit();
      });
    
      it('Component instantiated successfully', () => {
        expect(component).toBeTruthy();
      });
    
    });
    

    That's it. You can now reuse the utility method in all your spec files. You can also create a beforeAll utility method if that suits you better.

    0 讨论(0)
  • 2020-12-18 04:08

    You can create reusable const that contains the commom imports, providers from the modules you want.

    for example in a app.providers.ts file you can have your providers like this:

    import service1 from '.path/service/service1';
    import service2 from '.path/service/service2';
    
    export const providers = [service1, service2 ];
    

    and for your imports in a app.imports.ts

    import { BrowserModule } from '@angular/platform-browser';
    import { AppRoutingModule } from './app-routing.module';
    import { Module1} from ''.path/service/module1';
    
    export const imports= [
        BrowserModule,
        AppRoutingModule,
        Module1
    ],
    

    and on your app.module.ts and any other module you wanna use the same imports and providers you can do:

    import { providers } from './app.providers';
    import { imports } from './app.imports';
    @NgModule({
        declarations: [AppComponent],
        imports: imports,
        providers: providers,
        bootstrap: [AppComponent]
    })
    

    You can also use the spread operator to add your unique imports to these shared imports on a specific module.

    0 讨论(0)
提交回复
热议问题