2017-12-04 1 views
1

Ich versuche, eine Funktion zu testen, die Daten von einer externen API mithilfe von Axios erhält. Um meine Testfunktion so nah wie möglich an der realen Sache zu halten, frage ich nach Scheindaten, die ich in einer Datei habe. Axios kann keine Daten von lokalen Dateien zurückgeben, was eine Sicherheitsfunktion ist. Die Lösung, die ich versuche, besteht darin, einen einfachen Server in meiner Testsuite zu starten, die Datei dort zu verwalten und dann meine Tests auszuführen.Kann ich einen Express.js-Server in meiner Jest-Testsuite erstellen?

Meine Testsuite sieht wie folgt jetzt:

import React from 'react'; 
import {shallow} from 'enzyme'; 
import express from 'express'; 
import { getFeedId, getFeedData, reverseStop } from '../mocks/apiMock'; 

const app = express(); 
const port = 4000; 
app.use(express.static('../mocks/MockData.json')); 
app.listen(port, tests()); 

function tests() { 
    it('returns the expected feed id for a given subway line',() => { 
     expect(getFeedId('L')).toBe(2); 
    }); 

    it('returns json data',() => { 
     expect.assertions(2); 
     return getFeedData('L').then(data => { 
      expect(data).toBeDefined(); 
      expect(data.header.gtfs_realtime_version).toBe('1.0'); 
     }); 
    }); 

    it('returns a stop_id for a given subway line and stop',() => { 
     expect(reverseStop('L', 'Lorimer St')).toBe('L10N'); 
    }); 
} 

Die Funktionen Ich teste wie folgt aussehen (die, die verwendet Axios getFeedData ist, so dass ich glaube nicht, die anderen ein Problem verursacht aber ich bin nicht positiv).

const axios = require('axios'); 

export function getFeedId (sub) { 
    switch (sub) { 
     case '1': case '2': case '3': case '4': case '5': case '6': case 'S': 
      return 1; 
     case 'A': case 'C': case 'E': 
      return 26; 
     case 'N': case 'Q': case 'R': case 'W': 
      return 16; 
     case 'B': case 'D': case 'F': case 'M': 
      return 21; 
     case 'L': 
      return 2; 
     case 'G': 
      return 31; 
    } 
} 

export function getFeedData (sub) { 
    if (getFeedId(sub) === 2) { 
     return axios.get('http://localhost:4000').then((data) => JSON.parse(data)); 
    } 
} 

export function reverseStop (sub, stop) { 
    const stops = require('../utils/stops'); 
    const stopObjs = stops.filter((item) => item.stop_name == stop && typeof item.stop_id === 'string' && item.stop_id.charAt(0) == sub); 
    for (var i = 0; i < stopObjs.length; i++) { 
     if (stopObjs[i].stop_id.charAt(stopObjs[i].stop_id.length - 1) == 'N') { 
      return stopObjs[i].stop_id; 
     } 
    } 
} 

Hier ist die Fehlermeldung mich Jest schenkt:

bei der Ausgabe
FAIL src/tests/api.test.js (23.311s) 
    ● returns json data 

Network Error 

    at createError (node_modules/axios/lib/core/createError.js:16:15) 
    at XMLHttpRequest.handleError [as onerror] (node_modules/axios/lib/adapters/xhr.js:87:14) 
    at XMLHttpRequest.callback.(anonymous function) (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:289:32) 
    at invokeEventListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:219:27) 
    at invokeInlineListeners (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:166:7) 
    at EventTargetImpl._dispatch (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:122:7) 
    at EventTargetImpl.dispatchEvent (node_modules/jsdom/lib/jsdom/living/events/EventTarget-impl.js:87:17) 
    at XMLHttpRequest.dispatchEvent (node_modules/jsdom/lib/jsdom/living/generated/EventTarget.js:61:35) 
    at dispatchError (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:994:9) 
    at validCORSHeaders (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:1009:7) 
    at receiveResponse (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:871:12) 
    at Request.client.on.res (node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:691:38) 
    at emitOne (events.js:96:13) 
    at Request.emit (events.js:191:7) 
    at Request.onRequestResponse (node_modules/request/request.js:1074:10) 
    at emitOne (events.js:96:13) 
    at ClientRequest.emit (events.js:191:7) 
    at HTTPParser.parserOnIncomingClient (_http_client.js:522:21) 
    at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23) 
    at Socket.socketOnData (_http_client.js:411:20) 
    at emitOne (events.js:96:13) 
    at Socket.emit (events.js:191:7) 
    at readableAddChunk (_stream_readable.js:178:18) 
    at Socket.Readable.push (_stream_readable.js:136:10) 
    at TCP.onread (net.js:560:20) 

    ● returns json data 

expect.assertions(2) 

Expected two assertions to be called but only received zero assertion calls. 

    at addAssertionErrors (node_modules/jest-jasmine2/build/setup-jest-globals.js:68:21) 
    at process._tickCallback (internal/process/next_tick.js:109:7)``` 

Meine beste Vermutung ist, dass vielleicht Jest in einer Knotenumgebung nicht ausgeführt wird (ist es eine Möglichkeit, diese Zahl kann aus)? Vielleicht wird der Express-Server überhaupt nicht ausgeführt. Allerdings bin ich ein wenig über meine Sachkenntnis hinaus, so dass es wenig mehr als eine Vermutung ist. Kann jemand ein wenig Licht auf das werfen, was wirklich vor sich geht? War meine Idee, den Express-Server zu betreiben, ein guter? War es eine gute Idee, es in die Testsuite zu bringen? Wenn die Antwort auf eine oder beide dieser Fragen "nein" lautet, was sind die besten Praktiken hier?

+0

Wenn es nicht in Knoten ausgeführt wurde, würde Express selbst Fehler geben. – SLaks

+0

Randnotiz: Sie übergeben keinen Callback an 'listen()'. Eine zu übergeben könnte Ihr Problem lösen. – SLaks

+0

Ich gebe keinen Rückruf, um zu hören? Ich dachte, 'tests()' übergeben zu werden, da der zweite Parameter mein Callback war. Sie sagen auch unten, dass 'beforeEach()' async ist und übergeben Sie den Callback an 'listen()'. Ist 'listen()' nicht in 'beforeEach()' enthalten? – bkula

Antwort

1

Sie sollten Ihren Server beforeEach() (und stoppen Sie es in afterEach()), so dass es für jeden Test ausgeführt wird.

docs.

Sie sollten auch einen unbenutzten Port auswählen, damit Tests parallel ausgeführt werden können.

+0

Wie würde ich einen unbenutzten Port auswählen? Muss ich Express auf einen zufälligen Port hören lassen? Der Weg dahin, wenn ich mich nicht irre, ist, 'app.listen()' leer zu lassen, also wie würde ich dann meinen Callback hinzufügen? Wenn ich den Server 'beforeEach()' erstelle, muss ich meinen Callback überhaupt ändern? – bkula

+1

@bkula: Übergeben Sie "0". https://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback – SLaks

+0

Danke, aber ich bin immer noch verwirrt darüber, wie mein Callback aussehen sollte. Wenn ich 'app.listen()' einen Callback überlasse, der jeden Test ausführt, stört das nicht den Zweck der Verwendung von 'beforeEach()'? Muss ich sie irgendwie durchlaufen? Oder wird der Code in 'beforeEach()' noch vor jedem Test ausgeführt? – bkula

Verwandte Themen