如何在不使用 TestBed 的情况下模拟 Angular 中的 ActivatedRoute

How to mock ActivatedRoute in Angular without using TestBed

问题很简单。我从来都不喜欢原始测试在 Angular(TestBed 部分)中的工作方式,所以我一直以经典方式进行测试:使用 ts-mockito[=29= 进行模拟].没有 TestBed,无需配置,零混淆。我什至使用 Jest 而不是 Karma/Jasmine.

但是当谈到嘲笑 ActivatedRouter 时,我总是遇到麻烦,因为我猜你们中有很多人。我见过的一种解决方案是拥有一个对象,该对象具有 ActivatedRouter 所具有的大量属性,并替换您想要模拟的 属性 的值。该解决方案非常烦人,而且非常不可持续。

另一种解决方案被强制使用我不太喜欢的 TestBed,并执行以下操作:

providers: [
        {
          provide: ActivatedRoute,
          useValue: {
            snapshot: {
              paramMap: {
                get: () => 'foo'
              },
              queryParamMap: {
                get: () => 'bar'
              }
            }
          }
        }
      ]

这个确实不错,但正如我所说,它迫使你使用 TestBed。那么,如何在不使用 TestBed 的情况下模拟 ActivatedRoute 行为?

所以,今天我想出了一个很好的方法来模拟它 不必使用 TestBed.

这将是一个完整测试如何使用 ts-mockito:

的小示例
function setup() {
  const route = mock(ActivatedRoute);
  const routeInstance = instance(route);
  Object.defineProperty(routeInstance, 'snapshot', {
    writable: true,
    configurable: true,
    value: {
      paramMap: {
        get: () => 'someParam'
      },
      queryParamMap: {
        get: () => 'someQueryParam'
      }
    }
  });

  return {
    sut: new MyComponent(routeInstance),
    route
  };
}

describe('MyComponent', () => {
  it('should get param and query param from activated route', async () => {
    const { sut, route } = setup();

    const actualParam = sut.getParam();
    expect(actualParam).toBe('someParam');

    const actualQueryParam = sut.getQueryParam();
    expect(actualQueryParam).toBe('someQueryParam');
  });
});