2016-02-26 24 views
7

Tôi muốn thử nghiệm một phương thức bên trong thành phần Angular 2 được đăng ký với một quan sát được trả về từ một phương thức trong một dịch vụ. Dưới đây là mã cho phương pháp dịch vụ tóm tắt:Thử nghiệm một phương pháp được đăng ký với một quan sát - Angular 2

public create(user: User): Observable<any> { 
    return this.http.post(this._api.create, 
    JSON.stringify(user), { 
     headers: this.apiConfig.getApiHeaders() 
    }).map((res: Response) => res.json()); 
    } 

Thật dễ dàng để đơn vị kiểm tra phương pháp này vì nó trả về một quan sát để tôi có thể đăng ký nó. Nhưng tôi muốn thử nghiệm phương pháp này trong các thành phần đó đã được đăng ký này:

public onSubmit(user: User): void { 
    this._authentication.create(user).subscribe((token) => { 
    localStorage.setItem('token', token); 
    this.router.navigate(['/Home']); 
    }); 
} 

Heres spec của tôi cho đến nay nhưng khi tôi cố gắng spyOn các localStorage.setItem nó trở lại như không được gọi. Sự hiểu biết của tôi là nó có thể kiểm tra xem nó đã được gọi trước khi nó thực sự được gọi.

it('Should login a user and on success store a token in localStorage', 
    injectAsync([TestComponentBuilder], (tcb) => { 
    return tcb.createAsync(Login).then((fixture) => { 
     let instance = fixture.debugElement.componentInstance; 
     localStorage.clear(); 
     spyOn(localStorage, 'setItem'); 
     instance.onSubmit({userId: '[email protected]', password: 'password', siteName: 'sample'}); 
     expect(localStorage.setItem).toHaveBeenCalled(); 
    }); 
    }) 
); 

Tôi tự hỏi liệu mình có cần thử phương thức this._authentication.create để trả về một phương thức mới có thể quan sát được bằng phản hồi giả trong đó không? Sau khi nghiên cứu thêm một vài bài báo chỉ ra rằng tôi cần phải giả lập dịch vụ và trả về một Observable.of() chạy đồng bộ để giải quyết vấn đề, sao chép mã dưới đây một cách không đúng. Điều này tuy nhiên vẫn không hoạt động, tôi đã làm việc này hầu hết trong ngày, tôi không cảm thấy điều này nên được khó khăn, bất kỳ sự giúp đỡ đánh giá cao.

class MockAuthentication extends Authentication { 
    public create(user: Object): Observable<any> { 
    return Observable.of({'test': 'test'}); 
    } 
} 

Trả lời

2

Ok vì vậy nó đã đưa tôi hầu hết trong ngày nhưng cuối cùng tôi đã bẻ khóa. Thay vì sử dụng injectAsync và TestComponentBuilder để thiết lập spec, tôi chỉ cần sử dụng inject và inject thành phần giống như bạn làm một dịch vụ. Điều này có vẻ tốt bởi vì tôi không cần phải kiểm tra bất cứ điều gì trong quan điểm như các sự kiện.

Heres spec cuối cùng mà không làm việc:

it('Should set token in localStorage, set the new user, 
and navigate to home page on succesful login', 
    inject([Login], (login) => { 
    login.router.config([ { path: '/', name: 'Home', component: Home }]); 
    spyOn(localStorage, 'setItem'); 
    spyOn(login._currentUser, 'set'); 
    spyOn(login.router, 'navigate'); 
    login.onSubmit({ userId: '[email protected]', password: 'password', siteName: 'sample' }); 
    expect(localStorage.setItem).toHaveBeenCalledWith('token', 'newToken'); 
    expect(login._currentUser.set).toHaveBeenCalledWith({ 'test': 'one' }); 
    expect(login.router.navigate).toHaveBeenCalledWith(['/Home']); 
})); 

Hy vọng điều này có thể giúp đỡ một người nào đó trong tương lai.

1

Tôi đoán bạn muốn tiêm một mock Router dụ để thành phần của bạn và sau đó sau khi navigate(['/Home']) đã kêu gọi các mock Router, bạn kiểm tra xem localStorage.setItem(...) được gọi.

+0

Nó cảm thấy như việc kiểm tra sẽ xảy ra trước khi họ bị gọi là vì đăng ký nhưng tôi mới để quan sát. Ngoài ra, chúng tôi sử dụng để chỉ sử dụng spyOn (localStorage, 'setItem') trong Angular 1 nhưng tôi đang gặp khó khăn trong việc tìm ra cách làm tương tự với Angular 2. – HomeBrew

+0

Tệ của tôi, có vẻ như bạn vẫn sử dụng spyOn, vấn đề của tôi là tôi không thể tìm ra nơi bạn cần phải nhập khẩu 'spyOn' từ nhưng có vẻ như bạn chỉ có nó. Nhưng có vẻ như tuyên bố của tôi về việc kiểm tra xảy ra trước khi vẫn chạy đúng. Tôi đã cập nhật câu hỏi của mình để bao gồm thông số. – HomeBrew

-1

See my gist here.

Về cơ bản, bạn có thể thực hiện một số việc ở đây. Trước hết, hãy gọi http của bạn (tôi đoán từ một dịch vụ) với một phản ứng quan sát đơn giản của mã thông báo (hoặc phản hồi khác) mà bạn muốn.

service.stub.ts

export class MyStub { 
    public create(user: User): Observable<User> { 
    return Observable.of('insert test token here'); 
    } 
// other stubbed methods ... 
} 

Và sau đó bên trong thử nghiệm của bạn:

myComp.spec.ts

let comp: MyComponent; 
let fixture: ComponentFixture<MyComponent>; 
let sst: ServiceStub; 
describe('MyComponent',() => { 
    beforeEach(async(() => { 
    TestBed.configureTestingModule({ 
     declarations: [MyComponent], 
     schemas: [NO_ERRORS_SCHEMA] 
    }).overrideComponent(OnboardFacilityNewComponent, { 
     set: { 
     providers: [ 
      { provide: MyService, useClass: ServiceStub }, 
     ] 
     } 
    }) 
    .compileComponents() 
     .then(() => { 
     fixture = TestBed.createComponent(MyComponent); 
     comp = fixture.componentInstance; 
     st = fixture.debugElement.injector.get(MyService); 
     }); 
    })); 
    it('should submit new onboardFacility', fakeAsync(() => { 
    const sst = spyOn(sst, 'create').and.returnValue(
     Observable.of('some token here') 
    ); 
    comp.onSubmit(testUser); 
    fixture.detectChanges(); 
    expect(comp.token).toEqual('some token here'); 
    expect(spy.calls.any()).toEqual(true); 
    })); 
}); 

Ở đây, bạn chỉ có thể thay thế dữ liệu thực tế với số liệu kiểm tra để kiểm tra hành vi của thử nghiệm của bạn, thay vì sau đó testbed của bạn, dịch vụ của bạn, localStorage, vv Rõ ràng là thử nghiệm tôi đã viết ở đây giả định bạn sẽ lưu trữ các mã trả lại từ dịch vụ của bạn trong thành phần của bạn, r ather localStorage (though there is a way to do that), nhưng tôi chỉ đơn giản là hiển thị khái niệm thay vì trường hợp sử dụng cụ thể của bạn.

Trong trường hợp sử dụng của bạn, bạn cũng sẽ cần phải stub router, mà bạn có thể học cách làm here.

+0

Điều này không có ý nghĩa .. Tại sao bạn gọi spyOn trong một mô hình dịch vụ? Nếu nó được chế nhạo, nó cũng trả về một giá trị giả, bạn không cần phải trả về một giá trị giả khác với hàm returnValue Jasmine. –

+0

@EliasGarcia vì bạn đang xác định xem hàm logic có gọi là phụ thuộc hay không. Các điệp viên là tùy chọn. –

Các vấn đề liên quan