簡體   English   中英

如何在對解析器進行單元測試時模擬 ActivatedRouteSnapshot

[英]How to mock ActivatedRouteSnapshot when unit testing a Resolver

我想為我的解析器編寫一個單元測試,它需要在其構造函數中使用ActivatedRouteSnapshot ,如下所示:

export class MyResolver {
  constructor () {
    // ...
  }

  resolve (private route: ActivatedRouteSnapshot) {
    callFoo(route.params.val);
  }
};

但是在我的單元測試中,提供帶有模擬數據的激活路由快照的最佳方法是什么? 當我嘗試創建僅包含我需要的屬性的 object 時,出現無法將其轉換為 ActivatedRouteSnapshot 的錯誤:

it('should call foo', inject([MyResolver], async (myResolver: MyResolver) => {
  const mockRoute = {
    params: {
      val: '1234'
    };
  };

  sinon.spy(callFoo);
  myResolver.resolve(mockRoute); // This is the line that errors
  expect(callFoo.calledWith('1234')).to.be.true;
}));

錯誤:

Type '{ params: { val: string; }; }' cannot be converted to type 'ActivatedRouteSnapshot'.

我如何提供模擬的 ActivatedRouteSnapshot 以傳遞給我的解析器?

您必須像這樣提供活動路線:

import {TestBed} from '@angular/core/testing';
import {SomeResolver} from './some.resolver';
import {ActivatedRoute, convertToParamMap} from '@angular/router';
import {of} from 'rxjs';

describe('SomeResolver', () => {
  let someResolver: SomeResolver;
  let route: ActivatedRoute;

  TestBed.configureTestingModule({
    providers: [
      {
        provide: ActivatedRoute,
        useValue: {snapshot: {paramMap: convertToParamMap({id: 'one-id'})}}
      },
      SomeResolver
    ]
  });

  beforeEach(() => {
    heroResolver = TestBed.get(HeroResolver);
    route = TestBed.get(ActivatedRoute);
  });

  it('should resolve', (() => {
    someResolver.resolve(route.snapshot);
  }));
});

在此處查看更復雜的示例。

我不確定這是否是最漂亮的解決方案,但您可以像這樣模擬路線:

let route = createSpyObj('Route', ['']);
route.params = {
  val: '1234'
}

如果目的只是將模擬傳遞給解析器,則沒有必要像其他答案中建議的那樣使用createSpyObj 此外,最好在解決方案中添加類型安全性:

const mock = <T, P extends keyof T>(obj: Pick<T, P>): T => obj as T;

it('should call foo', () => {
    const route = mock<ActivatedRouteSnapshot, 'params'>({
        params: {
            val: '1234'
        }
    });

    const resolver = createTheResolver();
    const resolverParams = resolver.resolve(route);
    ...
});
import createSpyObj = jasmine.createSpyObj;

let route = createSpyObj('Route', ['']);
route.params = {
  nameOfParam: 'test'
}

就我而言,這是最簡單的事情(這也允許我寫入通常為只讀的“父”屬性:

const route = Object.assign({}, ActivatedRouteSnapshot.prototype, {
  params: {
    myParam: 'some_value'
  },
  parent: {
    params: {
      myParentParam: 'some_other_value'
    }
  }
});

然后你只需像這樣用'route'調用你的解析器:

it('should do something with my activated route params', (done) => {
const route = Object.assign({}, ActivatedRouteSnapshot.prototype, {
  params: {
    myParam: 'some_value'
  },
  parent: {
    params: {
      myParentParam: 'some_other_value'
    }
  }
});
service.resolve(route).subscribe(res => {
  expect( ... )
  done();
});
});

請注意,如果您願意,您也可以簡單地將您的對象轉換為 ActivatedRouteSnapshot:

const mockRoute = {paramMap: convertToParamMap({'id': '123'})} as 
    ActivatedRouteSnapshot;

resolver.resolve(mockRoute);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM