在Angular中进行服务依赖测试

时间:2019-03-14 20:02:37

标签: javascript angular unit-testing karma-runner

我正在尝试编写我的第一个Angular 6测试。我有一个组件,可以从服务中返回公司列表。

它看起来像这样:

模板

 <div *ngFor="let company of this.companies">
  <h4 id="company-{{company.id}}>{{company.name}}</h4>
 </div>

Component.ts

import { ApiService } from '../service/api.service';

ngOnInit(): void {
  this.companies = this.apiService.getCompanies();
}

服务

import { COMPANYLIST } from '../companyList';

companyList = COMPANYLIST;

public getCompanies(): Company[] {
  return this.companyList;
}

我想测试一下是否可以在组件中看到“公司”列表。在我的spec.ts中,我尝试根据https://angular.io/guide/testing#component-with-a-dependency添加模拟的apiService,但是没有运气。

我猜测试应该看起来像这样,但是实际上在将模拟服务注入到该测试中时遇到了问题。

  it("should show the list of Companies", () => {
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector("company-" + this.company.id).textContent).toContain("Mock Company");
  });

3 个答案:

答案 0 :(得分:0)

该策略是为您的服务注入一个占位符对象。在测试中,获取对该占位符对象的引用,然后向其添加虚假功能,在测试组件时将调用该虚假功​​能。

示例(我省略了无法说明我要表达的观点的代码

import { ApiService } from '../service/api.service';

describe('CompaniesComponent Tests', () => {

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [CompaniesComponent],
            providers: [
                { provide: ApiService, useValue: {} }
            ]
        }).compileComponents();
        TestBed.compileComponents();
        fixture = TestBed.createComponent(CompaniesComponent);
        comp = fixture.componentInstance;
    });


    it("should show the list of Companies", () => {
      // get service and fake a returned company list 
      const apiService = TestBed.get(ApiService) as ApiService;
      apiService.getCompanies = () => ['Mock Company'];

      // you probably need to call ngOnInit on your component so it retrieves the companies from the api service
      comp.ngOnInit();
      const compiled = fixture.debugElement.nativeElement;
      expect(compiled.querySelector("company-" + this.company.id).textContent).toContain("Mock Company");
    });

答案 1 :(得分:0)

您可以嘲笑您的服务:

export class MockCompanyService {

  getCompanies: Spy;

  constructor(config) {
    this.getCompanies = jasmine.createSpy('getCompanies').and.callFake(() => config.companies);
   }
}

在测试中,您将给companies嘲笑,这样,在调用函数时,将显示您的公司。

describe('CompanyComponent', () => {
  let component: CompanyComponent;
  let fixture: ComponentFixture<CompanyComponent>;
  let element;

  const mockCompanies = [
     ...
  ]; 

  beforeEach(async(() => {
    return TestBed
      .configureTestingModule({
        declarations: [
          CompanyComponent
        ],
        imports: [],
        providers: [
          {
            provide: ComponentFixtureAutoDetect,
            useValue: true
          }
        ]
      })
      .overrideComponent(CompanyComponent, {
        set: {
          providers: [
            {provide: CompanyService, useValue: new MockCompanyService(mockCompanies)}
          ]
        }
      })
      .compileComponents()
      .then(() => {
        fixture = TestBed.createComponent(CompanyComponent);
        component = fixture.debugElement.componentInstance;
        element = fixture.debugElement.nativeElement;
      });
  }));


  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('...', () => {

  });
});

答案 2 :(得分:0)

在您的示例中,单元测试应该非常容易实现。

应该是这样的:

describe("path", () => {

   let component: Component; 
   let fixture: ComponentFixture<Component>
   let service: Service;

   beforeEach(() => {
     TestBed.configureTestingModule({
      declarations: [Component],
      providers: [Service]
    });

    fixture = TestBet.CreateComponent(Component)
    service = TestBed.get(Service)
   });

   afterEach(() => {
     fixture.destroy();
   });

   it("Component_Method_WhatDoYouExpect", () => {
      let testCompanies = [{c1}....];

      let spy = spyOn(service, "getCompanies").and.returnValue(testCompanies);

      component.ngOnInit();

      expect(spy).toHaveBeenCalled();
      expect(component.companies).toEqual(testCompanies);
   });
});

您必须为组件创建一个测试文件,为服务创建一个。 在服务测试中,您应该执行与上述几乎相同的操作,但是您必须在此处初始化公司列表,调用该方法并验证结果是否正确。

service.companyList = [c1,c2 ...]

让res = service.GetCompanies();

expect(res).toEqual(service.companyList);

Here,您可以找到有关TestBed和单元测试的更多信息。