2017-04-01 5 views
6

Einige der Code, den ich zu Test bin versucht, die Plattform erkennt, zu verwenden, zB:Mocking Plattform Erkennung in Jest und Reagieren india

import { Platform } from 'react-native'; 
... 

if (Platform.OS === 'android') { 
    ... 
} else { 
    ... 
} 

Gibt es eine vernünftige Möglichkeit, dies mit Jest und/oder etwas anderes zu verspotten , also kann ich beide Zweige in einem Testlauf testen?

Oder ist die intelligente Art, es zu entkoppeln und die Plattform in z. B. eine Kontextvariable zu setzen? Es fühlt sich zwar immer nach Restrukturierungscode an, um das Testen zu erleichtern, ist aber etwas wie ein Betrüger.

Antwort

2

Diese (Jest 21.2.1, Enzyme 3.2.0) für mich gearbeitet direkt eingestellt werden:

jest.mock('Platform',() => { 
    const Platform = require.requireActual('Platform'); 
    Platform.OS = 'android'; 
    return Platform; 
}); 

Setzen Sie es entweder an der Spitze Ihres Tests oder in a beforeAll zum Beispiel.

0

können Sie verspotten, was Sie von React-Native wie diese wollen:

describe('notifications actions tests',() => { 
    let Platform; 


    beforeEach(() => { 
    jest.mock('react-native',() => ({ 
      Platform: { 
      ... 
     })); 


    Platform = require('react-native').Platform; // incase u would like to refer to Platform in your tests 
    }); 
+0

Macht es das nicht dauerhaft? d. h., wird das nicht bedeuten, dass ich in einem "afterEach" "uncock" machen muss? Ist das möglich? –

+0

Hmm, nein, das funktioniert nicht. 'jest.mock' wird gehisst, also ist es nicht in' beforeEach', also läuft es vor allem. Eine praktikable Option scheint das Affe-Patchen von 'RN.Platform.OS' vor einem Test zu sein. Oder Plattform in den Kontext entkoppeln. –

-1

Sie haben das Modul zu verspotten und in Ihren Test importieren. Dann können Sie mockImplementation verwenden, um die es entweder android oder ios

import reactNative from 'react-native'; 
jest.mock('react-native',() = > jest.fn(); 

it('is android',() => { 
    reactNative.mockImplementation(()=>({Platform:{OS: 'android'}})) 
    //test the android case 
}) 

it('is android',()=>{ 
    reactNative.mockImplementation(()=>({Platform: { OS: 'io' }})) 
    //test the ios case 
}) 
+1

Ich habe diese Methode versucht, aber ich bekomme '_reactNative2.default.mockImplementation ist keine Funktion'. Hast du irgendeine Idee? Vielen Dank. – Dan

+0

Das funktioniert nicht, da es als 'ReactNative.Platform.OS' definiert ist, nicht nur' ReactNative.Platform' –

+0

Sie haben Recht, ich habe die Antwort aktualisiert –

3

Die Art und Weise einstellen, dass ich spöttisch erzielen die Plattform Einstellung war es nur direkt gesetzt in den Tests:

it('should only run for Android',() => { 
    Platform.OS = 'android'; // or 'ios' 

    // For my use case this module was failing on iOS 
    NativeModules.MyAndroidOnlyModule = { 
    fetch: jest.fn(
     (url, event) => Promise.resolve(JSON.stringify(event.body)) 
    ), 
    }; 
    return myParentFunction().then(() => { 
    expect(NativeModules.MyAndroidOnlyModule.fetch.mock.calls.length).toBe(1); 
    expect(fetch.mock.calls.length).toBe(0); 
    }); 
}); 

Dies würde Setup des Plattform, die nur während Tests mit Android ausgeführt wird, um sicherzustellen, dass meine Funktion nur bestimmte Funktionen aufruft. Meine Funktion, die in plattformabhängige Zusammenstellung eingewickelt wurde aussah:

export default function myParentFunction() { 
    if (Platform.OS === 'ios') { 
    return fetch(); 
    } 
    return NativeModules.MyAndroidOnlyModule.fetch(); 
} 

würde ich vorschlagen, nur zwei verschiedene Tests Erstellen einer mit der Plattform iOS und das andere auf Android da idealerweise eine Funktion nur eine Verantwortung haben sollte. Ich bin mir jedoch sicher, dass Sie damit den ersten Test durchführen, die Plattform dynamisch einstellen und Test Nummer zwei in einer einzigen Funktion ausführen können.

-1

OS kann für jeden Test

test('android',() => { 
    Platform.OS = 'android' 
    const component = renderer.create(<Component />).toJSON() 
    expect(component).toMatchSnapshot() 
}) 
test('ios',() => { 
    Platform.OS = 'ios' 
    const component = renderer.create(<Component />).toJSON() 
    expect(component).toMatchSnapshot() 
}) 
+0

Downvotes ohne Erklärung hilft niemandem. Bitte erkläre – acharlop

0

Ich bin die Lösung aus dieser Github Ausgabe https://github.com/facebook/jest/issues/1370#issuecomment-352597475

mit zog ich den Scherz Config von package.json Dateien zu trennen. Bis jetzt scheint alles gut zu funktionieren, einschließlich: a) die richtige Datei wird entsprechend der Plattform importiert. Zum Beispiel auf ios: .ios.tsx, dann .native.tsx dann .tsx b) PLATTFORM.IOS gibt true zurück, wenn Test-ios läuft, keine Notwendigkeit

// package.json 
"scripts": { 
    "test": "cross-env NODE_ENV=test jest --config config/jest.desktop.json", 
    "test-ios": "cross-env NODE_ENV=test jest --config config/jest.ios.json", 
    "test-android": "cross-env NODE_ENV=test jest --config config/jest.android.json" 
} 

// config/jest.web.json 
{ 
... 
} 

// config/jest.ios.json 
{ 
... 
    "preset": "react-native", 
    "haste": { 
    "defaultPlatform": "ios", 
    "platforms": [ 
     "android", 
     "ios", 
     "native" 
    ], 
    "providesModuleNodeModules": [ 
     "react-native" 
    ] 
    }, 
} 

// config/jest.android.json 
{ 
... 
    "preset": "react-native", 
    "haste": { 
    "defaultPlatform": "android", 
    "platforms": [ 
     "android", 
     "ios", 
     "native" 
    ], 
    "providesModuleNodeModules": [ 
     "react-native" 
    ] 
    }, 
} 
1

Da die anderen Antworten alles verspotten wird nicht funktionieren, wenn Sie OSs anders verspotten wollen in der gleichen Testsuite und in einem Testlauf, hier ist ein anderer Weg. Statt Platform.OS direkt im Code verwenden, definieren Sie eine Hilfsfunktion irgendwo und verwenden Sie diese:

export function getOS() { 
    return Platform.OS; 
} 

Diese Funktion kann dann in Ihren Tests verspottet werden, z.B.

it('does something on Android',() => { 
    helpers.getOS = jest.fn().mockImplementationOnce(() => 'android'); 
    // ... 
} 

it('does something else on iOS',() => { 
    helpers.getOS = jest.fn().mockImplementationOnce(() => 'ios'); 
    // ... 
} 

Kredit für die Idee geht an this GitHub issue comment.