web-dev-qa-db-fra.com

unité testant spyOn service observable dans angular2

J'ai un service (ChildService) qui dépend d'un autre service (InteractWithServerService). Ce dernier service (InteractWithServerService) est utilisé pour effectuer des appels au serveur et renvoyer un observable de "n'importe quel" type. Par souci de simplicité, supposons qu'il renvoie un observable. J'essaie d'écrire un test unitaire pour ChildService.

ChildService

@Injectable()
export class ApplicationService {
    constructor(private  interactWithServerService:InteractWithServerService){;}

    public GetMeData():string {
        var output:string;       
        this.interactWithServerService.get("api/getSomeData").
           subscribe(response =>{console.log("server response:", response);
           output=response});        
         return output;
    }
}

ServerInteractionService

@Injectable()
export class InteractWithServerService {        
    constructor(private http: Http) {
        ;
    }    
    get(url: string): Observable<any> {        
        return this.http.get(this.url);
    }       
}

Le cas de test fonctionne bien lorsque je me moque du service dépendant. c'est à dire.,

class MockInteractWithServerService {
    get() {
        return Observable.of("some text");
    }           
}

describe('Service:ChildService', () => {
    let childService: ChildService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
             { provide: InteractWithServerService, useClass: MockInteractWithServerService },
                ChildService],
        });


    beforeEach(inject([ChildService], (actualService: ChildService) => {
        childService= actualService;        
    }));

    fit('should call server-call testCall()', () => {
        let actualReturnvalue= childService.GetMeData();        
        expect(actualReturnvalue).toBe("some text");
    });
});

La méthode ci-dessus n'est pas préférée car je pourrais finir par écrire des classes fictives "n" pour les dépendances "n". Je veux donc créer mes tests unitaires en utilisant spyOn. Cependant, le scénario de test ne fonctionne pas et génère "Erreur: aucun fournisseur pour Http!". Bien que je comprenne quelle est l'erreur, je voudrais savoir pourquoi elle est lancée bien que j'espionne le service dépendant. Il semble que "spyOn" ne fonctionne pas.

describe('Service:ChildService', () => {
    let childService: ChildService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
             InteractWithServerService,
                ChildService],
        });

        spyOn(InteractWithServerService.prototype, 'get').and
             .callFake(()=>      
          {return Observable.of("some text");});       
    });
    beforeEach(inject([ChildService], (actualService: ChildService) => {
        childService= actualService;        
    }));

    fit('should call server-call testCall()', () => {
        let actualReturnvalue= childService.GetMeData();        
        expect(actualReturnvalue).toBe("some text");
    });
});

Suis-je en train de manquer quelque chose d'évident?

12
Sudhir V

Cependant, le scénario de test ne fonctionne pas et génère "Erreur: aucun fournisseur pour Http!".

Parce que vous avez toujours le service dans le providers, donc Angular essaie de le créer toujours

providers: [
 InteractWithServerService,
    ChildService],

Ce que vous pouvez faire au lieu de créer une maquette classe est simplement de faire quelque chose comme

providers: [
  { 
    provide: InteractWithServerService,
    useValue: { get: Observable.of(..) }
  }
]

Voici que vous utilisez useValue qui fournit n'importe quel objet. Ce sera la valeur utilisée lors de l'injection. Dans le cas ci-dessus, il s'agit simplement d'un objet arbitraire avec votre méthode fictive.

Si vous souhaitez espionner afin de pouvoir fournir différentes valeurs, vous pouvez injecter le InteractWithServerService, puis faire

spyOn(service, 'get').and.returnValue(Observable.of(...))
// do test

Une autre chose que vous pourriez faire est de se moquer du Http avec un objet factice

{ provide: Http, useValue: {} }

Maintenant, le InteractWithServerService fonctionnera (il suffit d'ajouter la classe aux fournisseurs comme vous en avez actuellement). Et vous pouvez simplement l'espionner

let service = TestBed.get(InteractWithServerService);
spyOn(service, 'get').and.returnValue(..)
// do test
19
Paul Samsotha

En utilisant jasming 2.6.2: get est une fonction, vous devez donc ajouter la notation de la fonction flèche à la réponse ci-dessus:

providers: [
  { 
    provide: InteractWithServerService,
    useValue: { get: () => Observable.of(..) }
  }
]
0
dataphile