programing

ActivatedRoute의 매개 변수에 따라 구성 요소를 유닛 테스트하는 방법은 무엇입니까?

linuxpc 2023. 5. 1. 20:01
반응형

ActivatedRoute의 매개 변수에 따라 구성 요소를 유닛 테스트하는 방법은 무엇입니까?

개체를 편집하는 데 사용되는 구성 요소를 유닛 테스트하는 중입니다. 개체는 한 개가고니다를 가지고 .id서비스에서 호스팅되는 개체 배열에서 특정 개체를 가져오는 데 사용됩니다.id 변수를 됩니다. 라팅을통전는변통조다특니됩히달해를수개매우,ActivatedRoute학생들

생성자는 다음과 같습니다.

constructor(private _router:Router, private _curRoute:ActivatedRoute, private _session:Session) {}
    
ngOnInit() {
  this._curRoute.params.subscribe(params => {
    this.userId = params['id'];
    this.userObj = this._session.allUsers.filter(user => user.id.toString() === this.userId.toString())[0];

저는 이 부품에 대한 기본 단위 테스트를 실행하고 싶습니다.하지만, 저는 어떻게 주사를 놓을 수 있는지 확신할 수 없습니다.id매개 변수이며 구성 요소에는 이 매개 변수가 필요합니다.

그건 그렇고, 나는 이미 모의고사를 가지고 있습니다.Session서비스, 그러니까 걱정하지 마세요.

이를 위한 가장 간단한 방법은 그냥 사용하는 것입니다.useValue모의할 값의 관찰 가능한 값을 제공합니다.

RxJS < 6

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
...
{
  provide: ActivatedRoute,
  useValue: {
    params: Observable.of({id: 123})
  }
}

RxJS > = 6

import { of } from 'rxjs';
...
{
  provide: ActivatedRoute,
  useValue: {
    params: of({id: 123})
  }
}

8에는 에 8+는 .RouterTestingModule 있사수있다니습용할록도액에 할 수 .ActivatedRoute또는Router구성 요소의.또한 로의 경로를 전달할 수 있습니다.RouterTestingModule그리고 요청된 경로의 방법을 위해 스파이를 만듭니다.

예를 들어 내 구성 요소에는 다음이 있습니다.

ngOnInit() {
    if (this.route.snapshot.paramMap.get('id')) this.editMode()
    this.titleService.setTitle(`${this.pageTitle} | ${TAB_SUFFIX}`)
}

그리고 제 시험은 다음과 같습니다.

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ ProductLinePageComponent ],
      schemas: [NO_ERRORS_SCHEMA],
      imports: [
        RouterTestingModule.withRoutes([])
      ],
    })
    .compileComponents()
  }))

  beforeEach(() => {
    router = TestBed.get(Router)
    route = TestBed.get(ActivatedRoute)
  })

나중에 'it' 섹션에서 확인할 수 있습니다.

  it('should update', () => {
    const spyRoute = spyOn(route.snapshot.paramMap, 'get')
    spyRoute.and.returnValue('21')
    fixture = TestBed.createComponent(ProductLinePageComponent)
    component = fixture.componentInstance
    fixture.detectChanges()
    expect(component).toBeTruthy()
    expect(component.pageTitle).toBe('Edit Product Line')
    expect(component.formTitle).toBe('Edit Product Line')
    // here you can test the functionality which is triggered by the snapshot
  })

비슷한 방법으로, 저는 당신이 직접 테스트할 수 있다고 생각합니다.paramMap유로를 spyOnProperty관찰 가능한 것을 반환하거나 rxjs 대리석을 사용하여 재스민 방법.시간을 절약할 수 있고 추가 모의 수업을 유지할 필요가 없습니다.그것이 유용하고 이치에 맞기를 바랍니다.

어떻게 해야 할지 알아냈어요!

때부터ActivatedRoute는 서비스이며, 이를 위한 모의 서비스를 구축할 수 있습니다.이것을 모의 서비스라고 부르자.MockActivatedRoute는 연겠습다니를 할 것입니다.ActivatedRouteMockActivatedRoute같이 표시됩니다.

class MockActivatedRoute extends ActivatedRoute {
    constructor() {
        super(null, null, null, null, null);
        this.params = Observable.of({id: "5"});
    }

super(null, ....)4개의 필수 매개 변수가 있는 슈퍼 클래스를 초기화합니다. 중 하지 않기 하여 그나러, 경우이우, 이매한수중개, 우그초다니합기화, 리는을들것에때문않으로 설정합니다.null가치.우리가 필요로 하는 것은 가치입니다.params은 것은그입니다.Observable<>러므로와 함께, 함께와와 함께.this.params는 우는가치무니다합시의 합니다.params그리고 그것이 되도록 초기화합니다.Observable<>테스트 대상이 의존하는 매개 변수의.

그런 다음 다른 모의 서비스와 마찬가지로 초기화하고 구성 요소의 공급자를 재정의합니다.

행운을 빕니다.

제가 최근에 각도 2.0으로 테스트한 방법은 다음과 같습니다.

import { ActivatedRoute, Data } from '@angular/router';

및 공급자 섹션에서

{
  provide: ActivatedRoute,
  useValue: {
    data: {
      subscribe: (fn: (value: Data) => void) => fn({
        yourData: 'yolo'
      })
    }
  }
}

활성화된 경로에 대한 모의실험을 추가하기만 하면 됩니다.

providers: [
  { provide: ActivatedRoute, useClass: MockActivatedRoute }
]

...

class MockActivatedRoute {
  // here you can add your mock objects, like snapshot or parent or whatever
  // example:
  parent = {
    snapshot: {data: {title: 'myTitle ' } },
    routeConfig: { children: { filter: () => {} } }
  };
}

라우팅 경로에 대한 테스트 제품군을 만드는 동안 다음과 같은 문제가 발생했습니다.

{
   path: 'edit/:property/:someId',
   component: YourComponent,
   resolve: {
       yourResolvedValue: YourResolver
   }
}

구성 요소에서 전달된 속성을 다음과 같이 초기화했습니다.

ngOnInit(): void {    
   this.property = this.activatedRoute.snapshot.params.property;
   ...
}

테스트를 실행할 때 모의 ActiveRoute "useValue"에서 속성 값을 전달하지 않으면 "fix"를 사용하여 변경 사항을 감지할 때 정의되지 않습니다.변경사항()"을 검색합니다.이는 ActivatedRoute의 모의 값에 params.property 속성이 포함되어 있지 않기 때문입니다.그런 다음 fixture가 구성 요소에서 'this.property'를 초기화하려면 mock useValue에 이러한 매개변수가 있어야 합니다.다음과 같이 추가할 수 있습니다.

  let fixture: ComponentFixture<YourComponent>;
  let component: YourComponent;
  let activatedRoute: ActivatedRoute; 

  beforeEach(done => {
        TestBed.configureTestingModule({
          declarations: [YourComponent],
          imports: [ YourImportedModules ],
          providers: [
            YourRequiredServices,
            {
              provide: ActivatedRoute,
              useValue: {
                snapshot: {
                  params: {
                    property: 'yourProperty',
                    someId: someId
                  },
                  data: {
                    yourResolvedValue: { data: mockResolvedData() }
                  }
                }
              }
            }
          ]
        })
          .compileComponents()
          .then(() => {
            fixture = TestBed.createComponent(YourComponent);
            component = fixture.debugElement.componentInstance;
            activatedRoute = TestBed.get(ActivatedRoute);
            fixture.detectChanges();
            done();
          });
      });

다음과 같이 테스트를 시작할 수 있습니다.

it('should ensure property param is yourProperty', async () => {
   expect(activatedRoute.snapshot.params.property).toEqual('yourProperty');
   ....
});

이제 다른 속성 값을 테스트하고 싶다고 가정하면 다음과 같이 모의 활성화된 경로를 업데이트할 수 있습니다.

  it('should ensure property param is newProperty', async () => {
    activatedRoute.snapshot.params.property = 'newProperty';
    fixture = TestBed.createComponent(YourComponent);
    component = fixture.debugElement.componentInstance;
    activatedRoute = TestBed.get(ActivatedRoute);
    fixture.detectChanges();

    expect(activatedRoute.snapshot.params.property).toEqual('newProperty');
});

이것이 도움이 되길 바랍니다!

각도 11: 사양 파일에 추가합니다.

imports: [
   RouterTestingModule.withRoutes([])
],

이것은 단 한 줄로 도움이 됩니다. 다른 줄로 제공자를 조롱해야 합니다.

다음을 사용하여 이 작업을 수행할 수 있습니다.beforeAll기능.부터beforeAll당신의 모든 사람들 앞에 불려집니다.beforeEach함수를 사용하면 구성 요소가 컴파일되기 전에 구성원 변수를 변경할 수 있습니다.

describe('MyComponent', () => {

  let fakeActivatedRoute = {
    paramMap: of(convertToParamMap({ id: '123' })),
    queryParamMap: of(convertToParamMap({ query: 'active' }))};


  beforeEach(async() => {
    await TestBed.configureTestingModule({

      providers: [
        ...
        { provide: ActivatedRoute, useValue: fakeActivatedRoute }],
      }).compileComponents();
    });
  });

  describe('id is present in route', () => {
    beforeAll(() => {
      fakeActivatedRoute.paramMap = 
        of(convertToParamMap({ id: '123' }));
      fakeActivatedRoute.queryParamMap = 
        of(convertToParamMap({ query: '' }));
    });

    it('should call service to look up id', () => {
      ...
    });
  });

  describe('id is not present in route', () => {
    beforeAll(() => {
      fakeActivatedRoute.paramMap = 
        of(convertToParamMap({ id: '' }));
      fakeActivatedRoute.queryParamMap = 
        of(convertToParamMap({ query: '' }));
    });

    it('should not call service to look up id', () => {
      ...
    });
  });

  describe('query is present in route', () => {
    beforeAll(() => {
      fakeActivatedRoute.paramMap = 
        of(convertToParamMap({ id: '123' }));
      fakeActivatedRoute.queryParamMap = 
        of(convertToParamMap({ query: 'inactive' }));
    });

    it('should call service to look up the inactive id', () => {
      ...
    });
  });
});

Angular > 5에서 작업하는 일부 사용자의 경우, Observable.of();가 작동하지 않는 경우 'rxjs'에서 {of} 가져오기를 통해 ()만 사용할 수 있습니다.

테스트 클래스에 다음과 같이 공급자 추가:

{
  provide: ActivatedRoute,
  useValue: {
    paramMap: of({ get: v => { return { id: 123 }; } })
  } 
}

지금까지의 다른 모든 답변은 경로 매개 변수에 대한 값만 제공합니다.경로 변경 트리거 자체를 테스트하려면 어떻게 해야 합니까?source.next()를 사용하여 경로 변경을 트리거할 수 있도록 테스트의 활성화된 경로에 Subject 및 해당 Observable을 제공할 수 있습니다.

테스트 중인 코드:

    constructor(private readonly route: ActivatedRoute) {}

    ngOnInit(): void {
      this.routeParamSubscription = this.route.params.subscribe((params) => {
        if (params['id']) {
          this.loadDetails(params['id']);
        }
      });
    }

테스트 코드:

    let routeChangeSource: BehaviorSubject<Params>;
    // In TestBed.configureTestingMethod
    ...
      providers: [
        {
          provide: ActivatedRoute,
          useValue: {
            params: routeChangeSource.asObservable()
          }
        }
      ]
    ...
    it('loads data on route change', fakeAsync(() => {
      const spy = spyOn(component, 'loadDetails').and.callThrough();
      routeChangeSource.next({ id: 99 });
      tick();
      expect(spy).toHaveBeenCalledOnceWith(99);
    }));

이렇게 하면 경로 변경 후 트리거된 작업을 테스트하고 해당 작업이 활성화되었는지 확인합니다.

이 경우 매개 변수에 액세스하는 경우get의 방법paramMap

.ts에서:

this.id= this.activatedRoute.snapshot.paramMap.get('id');

.spec.ts에서

providers: [
        {
          provide: ActivatedRoute,
          useValue: {
            snapshot: {
              paramMap: {
                get() {
                  return '97dbf5d7';
                }
              }
            }
          }
        }
      ]

언급URL : https://stackoverflow.com/questions/38356084/how-to-unit-test-a-component-that-depends-on-parameters-from-activatedroute

반응형