कैसे एक इकाई परीक्षण करने के लिए एक घटक है कि ActivatedRoute से मापदंडों पर निर्भर करता है?


93

मैं एक घटक का परीक्षण करने वाली इकाई हूं जिसका उपयोग किसी वस्तु को संपादित करने के लिए किया जाता है। ऑब्जेक्ट में एक अद्वितीय है 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सेवा के लिए पहले से ही एक नकली है , इसलिए वहां कोई चिंता नहीं है।

जवाबों:


135

ऐसा करने का सबसे सरल तरीका यह है कि आप केवल useValueविशेषता का उपयोग करें और जिस मूल्य का आप मॉक करना चाहते हैं उसका एक अवलोकन प्रदान करें।

आरएक्सजेएस <6

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

आरएक्सजेएस> = 6

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

11
अवलोकनीय। मेरे लिए मौजूद नहीं है! : एस
एलेजांद्रो सैंज डिआज

4
Rxjs से अवलोकन योग्य आयात करें / अवलोकन करें
zmanc 13

6
यह कोड मेरे प्रोजेक्ट में यह त्रुटि करता है:Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest': Failed to load 'ng:///DynamicTestModule/HomeContentComponent.ngfactory.js'. at http://localhost:9876/_karma_webpack_/polyfills.bundle.js:2605
MixerOID

5
RxJs 6 ofका उपयोग अकेले किया जाना चाहिए। इसके अलावा आप RouterTestingModuleइस उत्तर के कोड के बजाय इसका उपयोग करेंगे ।
बेन रेसिकॉट

5
@ BenRacicot ने यह उत्तर RxJs 6 के अस्तित्व में आने से पहले दिया था। इसके बजाय "ऐसा करने के बजाय" सीधे उत्तर देने वाले उत्तर प्रदान करें।
zmanc

18

मुझे पता चला है कि यह कैसे करना है!

चूंकि ActivatedRouteएक सेवा है, इसके लिए एक नकली सेवा स्थापित की जा सकती है। आइए इस मॉक सेवा को कॉल करें MockActivatedRoute। हम विस्तार होगा ActivatedRouteमें MockActivatedRouteइस प्रकार है:

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

लाइन super(null, ....)सुपर क्लास को इनिशियलाइज़ करती है, जिसमें चार अनिवार्य पैरामीटर हैं। हालांकि, इस उदाहरण में, हमें इनमें से किसी भी पैरामीटर से कुछ भी नहीं चाहिए, इसलिए हम उन्हें nullमानों के लिए प्रारंभ करते हैं। हम सभी की जरूरत है जिसका मूल्य paramsएक है Observable<>। इसलिए, के साथ this.params, हम के मान को ओवरराइड करते हैं paramsऔर इसे इनिशियलाइज़ करने के लिए Observable<>उस पैरामीटर के आधार पर होते हैं जिस पर टेस्ट सब्जेक्ट निर्भर है।

फिर, किसी भी अन्य नकली सेवा के रूप में, बस इसे आरंभ करें और घटक के लिए प्रदाता को ओवरराइड करें।

सौभाग्य!


1
मैं अभी इसका सामना कर रहा हूं! हालाँकि, जब मैं उपयोग करने की कोशिश करता हूँ superया मैं त्रुटी करता हूँ Observable। ये कहां से आते हैं?
अनारोरा

super()में बनाया गया Observableहै rxjs/Observableया rxjsआपके संस्करण पर निर्भर करता है। आप इसका उपयोग कर लेंगे import {Observable} from 'rxjs'
oooyaya

आपने एक उत्तर स्वीकार किया है और दूसरा पोस्ट किया है ... यदि यह हाइलैंडर था (और केवल एक ही हो सकता है), तो आपने कौन सा "वास्तव में" चुना और क्यों? यही है, मुझे लगता है कि यह अनिवार्य रूप से ज़मान के जवाब के रूप में उसी चीज़ को कम करता है, जिसे आपने स्वीकार किया था। क्या आपने इसे स्थापित करने से अतिरिक्त मूल्य पाया [थोड़ा] अधिक जटिल नकली?
रफिन

11

कोणीय 8+ में RouterTestingModule है, जिसका उपयोग आप घटक के ActivatedRoute या Router तक पहुँचने के लिए कर सकते हैं। इसके अलावा, आप रूट रूटरिंगमॉडल को मार्ग पास कर सकते हैं और मार्ग के अनुरोधित तरीकों के लिए जासूस बना सकते हैं।

मेरे घटक में उदाहरण के लिए मेरे पास है:

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('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
  })

इसी तरह से, मुझे लगता है कि आप एक अवलोकनीय या rxjs पत्थर का उपयोग करके चमेली की जासूसी विधि के माध्यम से सीधे पैरामैप का परीक्षण कर सकते हैं। यह कुछ समय बचा सकता है और इसके लिए अतिरिक्त नकली वर्ग को बनाए रखने की आवश्यकता नहीं है। आशा है कि यह उपयोगी है और यह समझ में आता है।


एक अतिरिक्त नकली बनाए रखने की तुलना में बहुत बेहतर है और आप आसानी से परीक्षणों में विभिन्न मापदंडों को निर्धारित कर सकते हैं। धन्यवाद!
migg

इससे मदद मिलती है। क्या आप जानते हैं कि अलग-अलग पारामों की जासूसी कैसे की जाती है: const dirName = this.route.snapshot.paramMap.get ('dirName'); const actionType = this.route.snapshot.paramMap.get ('actionType'); किस बॉट पर जासूसी होगी (path.snapshot.paramMap, 'get')? क्या मैं सुनने के लिए कुंजी निर्दिष्ट कर सकता हूँ?
स्पेकसी

जैसा कि मैंने ऊपर उल्लेख किया है, मुझे लगता है कि आप जासूसी के बजाय spyOnProperty का उपयोग कर सकते हैं, उदाहरण के लिए spyOnProperty (path.snapshot.paramMap.get, 'dirName')। यदि मैंने आपके प्रश्न का पूरी तरह से उत्तर नहीं दिया है, तो मुझे बताने में संकोच न करें। धन्यवाद।
डिमिट्रिस माफ़

10

यहाँ है कि मैंने इसे एंगुलर 2.0 नवीनतम में कैसे परीक्षण किया ...

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

और प्रदाता अनुभाग में

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

क्या आप प्रदाताओं अनुभाग के लिए पूरा कोड प्रदान कर सकते हैं?
माइकल जेडीआई

यह एक पूर्ण इकाई परीक्षण वर्ग है। plnkr.co/edit/UeCKnJ2sCCpLLQCWqEGX?p=catalogue
Rady

आप ngOnDestroy
shiva

यह वास्तविक जीवन में टूट जाएगा क्योंकि आप सदस्यता वापस नहीं कर रहे हैं और आप ngOnDestroy में कॉल .unsubscribe () का उपयोग नहीं कर पाएंगे।
क्वोवैडिसक

1
डेटा: Observable.of ({yourData: 'yolo'}) हालांकि काम करेगा।
कोवाडिसक

4

बस ActivatedRoute का मज़ाक जोड़ें:

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: () => {} } }
  };
}

3

Angular> 5 पर काम करने वाले कुछ लोगों के लिए, यदि Observable.of (); काम नहीं कर रहा है तो वे 'rxjs' से {} का आयात करके () का उपयोग कर सकते हैं;


1

राउटिंग पाथ के लिए टेस्ट सूट बनाते समय इसी मुद्दे में भागे:

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

घटक में, मैंने उत्तीर्ण संपत्ति को निम्न के रूप में देखा:

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

परीक्षण चलाते समय, यदि आप अपने मॉक एक्टीवेटआउट "यूटील्यूव" में कोई प्रॉपर्टी वैल्यू पास नहीं करते हैं, तो "फिक्सचरटेटचेंजेज ()" का उपयोग करते हुए परिवर्तनों का पता लगाने पर आप अपरिभाषित हो जाएंगे। ऐसा इसलिए है क्योंकि ActivatedRoute के लिए नकली मानों में संपत्ति params.property शामिल नहीं है। फिर, यह घटक में 'this.property' को इनिशियलाइज़ करने के लिए फ़िराक के लिए उन परिमों के उपयोग के लिए आवश्यक है। आप इसे इस प्रकार जोड़ सकते हैं:

  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');
});

उम्मीद है की यह मदद करेगा!


0

परीक्षण वर्ग में प्रदाता के रूप में जोड़ा गया:

{
  provide: ActivatedRoute,
  useValue: {
    paramMap: of({ get: v => { return { id: 123 }; } })
  } 
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.