首页 > 解决方案 > Angular 7 测试依赖于私有方法的公共方法

问题描述

我正在使用 Angular 7.1 和 Jasmine 来测试我的组件。我正在尝试编写一些测试,但这对我来说似乎太多了。

我正在尝试测试的简化类:

import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'a',
  templateUrl: './a.html',
  styleUrls: ['./a.scss']
}
export class A implements OnInit {
  constructor(private http: HttpClient) {}
  private privateState: State;
  public publicState: State2;      

  ngOnInit() {
      this.http.get(this.GetUrl()).subscribe((x) => {
      this.privateState = x['whatever'];
    });
  }

  private hiddenComplexFunction() {
    this.publicState = this.privateState.something;
  }

  public testedFunction() {
    //someComplex Code
    this.hiddenComplexFunction();
  }
}

我试过的:

我不知道哪种方法是测试这个的正确方法。我知道我可以hiddenComplexFunction公开,我所有的问题都消失了,而且我不喜欢这样一个事实,即由于测试我必须更改访问修饰符(从私有到受保护的,就像在模拟示例中一样,这对我来说似乎都是错误的)。

标签: javascriptangularjasmine

解决方案


你的问题有很多内容,所以我将从我容易看到的事情开始。

我们可以从您的核心组件代码开始。在您的testedFunction() 中,调用this.hiddenComplexFunction()。你想要函数的实例版本,所以需要添加 ""this."" 到它。这是非常合适的,无论如何您都不想直接测试私有函数/私有属性。

接下来,我猜你想要这段代码

this.state = x['whatever'];

设置您的 privateState,而不是状态

this.privateState = x['whatever'];

接下来,您不需要使用 AMock 类模拟 A,测试装配将为您完成。尝试以下类似的方法作为开始。我在这里没有的是州代码。我真正做的就是摆脱你的 AMock 并用实际的组件替换它,并构建一个测试状态(我可能会添加一个糟糕的状态构建。哈!)。我处理下面的 HTTP 数据,这将与我通过查看您的代码猜测的状态有关。

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { A } from './zing.component';  // this should point to your component

// get rid of this, not needed
// class AMock extends A {
//   ngOnInit() {
//     //privateState is now protected
//     let privateState = mockedState;
//   }
// }

describe('A', () => {
  let component: A;  // changed from AMock to A
  let fixture: ComponentFixture<A>; // changed from AMock to A

  let mockedState = {something: 'yelp'}; // build your expected state here

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      declarations: [A] // changed from AMock to A
    })
      .compileComponents().catch();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(A); // changed from AMock to A
    component = fixture.componentInstance;
  });

  it('testedFunction should set up public state correctly', () => {
    component.testedFunction();

    expect(component.publicState).toEqual(mockedState.something);
  });
});

最后,对于您的 HTTP 模拟,您可以使用 HttpTestingController 将一些数据刷新到您的组件。

在描述块中 -

let backend: HttpTestingController;

在每个之前 -

backend = TestBed.get(HttpTestingController);

在您的 IT 声明中 -

backend.expectOne(expectedURL).flush(mockedState);

backend.verify();

让我们知道这对您有多大帮助,是否有帮助或您是否遇到其他错误。


推荐阅读