Automated tests give you confidence in the piece of code you write. Sometimes we write code that works locally then push to production. However, changes made breaks entirely different parts of the project. Someone else on your team might have written these parts of the project, but your changes caused conflicts. Testing prevents this. There are different types of tests: unit tests, integration tests, functional tests, end-to-end tests, and many more. What is unit testing? Using a car as an analogy, we all know that a car comprises of different components (Unless you live in a tree 🤪). These components comprise wheels, an engine, headlights, and taillights, etc. Unit tests basically ensure each individual component performs as expected. Looking at our car analogy, to ensure our wheel is perfectly round we rotate it by exerting external force, same way we write unit tests to ensure individual components of our source code (software) function as they ought to. In this article, we will be looking at the basic principles of unit tests with a simple react-native component. Button Let’s go ahead to create a component. Button React ; {Pressable, Text, View, StyleSheet} ; Button = { ( <View style={transparent ? styles.transparentBtn : styles.btn}> <Text style={transparent ? styles.transparentTitle : styles.title}> {isLoading ? 'Loading...' : title} </Text> </View> ); }; styles = StyleSheet.create({ : { : , : , : , : , : , : , : , }, : { : , : , : , : , : , : , }, : { : , : , }, : { : , }, }); Button; import from 'react' import from 'react-native' const ( ) => {onPress, title, isLoading, transparent} return { if (!isLoading) { return onPress(); } }}> < = => Pressable onPress {() </ > Pressable const btn width '100%' height 50 backgroundColor '#74B3CE' alignItems 'center' justifyContent 'center' marginVertical 10 borderRadius 4 transparentBtn width '100%' height 50 backgroundColor 'transparent' alignItems 'center' justifyContent 'center' marginVertical 10 title color 'white' fontSize 16 transparentTitle color '#74B3CE' export default Testing We test react-native using several tools. The first tool we will look at is Jest. Jest — Javascript testing framework. There are different testing frameworks, depending on the programming language tested. ‘Jest’ is one of the most preferred testing frameworks for React and React-native applications. There are other Javascript testing frameworks; Mocha, Jasmine, Karma, Puppeteer. React Native ships with Jest; we can skip its installation. ‘Jest’ discovers test files within our project via their file names, which can be at any depth in our project. There are three naming styles by which ‘Jest’ picks up our test files. — This is suitable for finding associated test files for a component. When you have App.js the test file is side-by-side as App.test.js or App.spec.js — This is preferrable for components that require multiple test files and large projects. Any file with a .test.js suffix or a .spec.js suffix Any files witing a test folder Enzyme — Enzyme helps test the output (rendering), interactivity, and manipulation of our React and React native components by simulation, as compiling and running our react-native application for testing would be a slow process. Enzyme’s syntax makes our lives easier while testing components 😁. An alternative to Enzyme is ‘react-test-renderer’, but we will make use of Enzyme as it contains more functionalities. To setup enzyme first run: npm install jest-environment-enzyme jest-enzyme enzyme-adapter-react-16 — save-dev npm install — save-dev react-dom enzyme Edit package.json — Add the following config to “jest” object : { [ ], : , : { : } } "jest" "setupFilesAfterEnv" "jest-enzyme" "testEnvironment" "enzyme" "testEnvironmentOptions" "enzymeAdapter" "react16" So lets get to it! Testing our component Button React ; Button ; {View, Text} ; {shallow} ; toJson ; describe( , () => { it( , () => { component = shallow( import from 'react' import from '../index' import from 'react-native' import from 'enzyme' import from 'enzyme-to-json' 'Button' 'should render without issues' const ); expect(component.length).toBe(1); expect(toJson(component)).toMatchSnapshot(); }); //... < /> Button , , - Are global variables in ‘Jest’; as a result, we don’t have to require or import anything to use them. describe it expect - This method creates a block or scope where we write several related tests. 'describe' takes in a name (should be descriptive) and then a callback where we write our actual tests describe(name, cb) - ‘it’ is an alias of test which has three parameters — a descriptive name of your choice, a callback function containing our test assertions, and an optional timeout that specifies how long to wait before the test aborts. The default timeout is 5 seconds. it(name, cb, timeout) - Expect is used when we want to test a value, we mostly use 'expect' alongside other functions called "matchers", to view all matchers you can check the link expect(value) Expect · Jest Testing “Button”, we call the method passing in a description and a callback indicating a shared relationship of every test assertions in the describe block. Then our first test assertion — makes sure the renders. describe it(‘should render without issues’, ….) Button Using from Enzyme, we run the component in isolation without rendering its children (In this instance, Button has no child component), calls the constructor of the component and the component’s method. shallow Button shallow render The number of components rendered (component.length) is expected to equal one using and the matcher. compares values or object instances, making it more suitable to the operator. expect toBe() toBe() === —We use to make sure we don’t cause unexpected changes to UI components. When we make deliberate changes to components, the test fails; as a result, we update our previous using Snapshots snapshots snapshots snapshots npm test — -u We use the to compare previous and current snapshots. When there isn’t an old snapshot, ‘Jest’ creates a new one. .toMatchSnapshot() To compare snapshots we use the method; it returns a compatible format of our component for ‘Jest’ snapshots. toJson( component ) The next thing we want to test is the event prop, but before doing, that let’s look at Mock functions in Jest. onPress — In Jest, mock functions allow us to test links between code. Jest mock functions let us erase the actual implementation, more like a placeholder. For example, testing a component that makes actual API calls, our test will be slow; hence we mock the API endpoint. Mock functions There are two ways to mock functions in ‘Jest’: Creating in test scripts.Writing to override dependencies. mock functions manual mocks For now, we will mock up a simple function below. We track of mock functions calls and return values; using the property. This is done using the , , properties. .mock .calls .return .instances it( , () => { result = ; mockFn = jest.fn( result); component = shallow( //... 'should call onPress event' const 'I was Pressed' const => () const ); expect(mockFn).not.toHaveBeenCalled(); component.props().onPress(); expect(mockFn.mock.calls.length).toBe(1); expect(component.props().onPress()).toBe(result); }); //... < = /> Button onPress {mockFn} We create a mock function which returns ‘ , then render our component using Afterwards simulate a press by calling . The method returns an object containing all props of a component. Considering the normal behavior of a button, pressing the component only once should call our mock function — which returns ‘ To test for this, is called twice Ensuring is called once, and its return value is correct. I was Pressed’ shallow(). props().onPress(). .props Button I was Pressed’. expect() . mockFn The next thing we want to make sure of is not calling when is onPress mockFn isLoading true . it( , () => { result = ; mockFn = jest.fn( result); component = shallow( //... 'should not call onPress event when loading is true' const 'I was pressed' const => () const ); component.props().onPress(); expect(mockFn.mock.calls.length).toBe(0); }); //... < = = /> Button isLoading {true} onPress {mockFn} When prop is , we simulate a press on Button, which shouldn’t trigger a call to mockFn. Therefore the number of calls to mockFn remains 0. isLoading true Next, we test if renders the correct title. Button it( , () => { title = ; component = shallow( //... 'button should render title passed to it' const 'Primary Button' const ); expect(component.find(Text).first().props().children).toBe(title); }); //... < = /> Button title {title} We use the method to obtain the Text component in , the child of should be the same as the prop. .find Button Text title Next, we test if the title of renders when Button ‘Loading…’ isLoading=== true it( , () => { component = shallow( //... 'should be Loading... text when isLoading === true' const ); component.setProps({isLoading: true}); component.update(); expect(component.find(Text).first().props().children).toBe('Loading...'); }); //... < = /> Button isLoading {false} We use to update the props passed to and force a re-render, then we check if the title rendered is setProps Button “Loading…” Next, we test if the styles of change when we pass the prop to Button transparent Button. it( , () => { transparentContainer = { : , : , : , : , : , : , }; transparentTitle = { : , }; component = shallow( //... 'should have transparent styles when transparent is true' const width '100%' height 50 backgroundColor 'transparent' alignItems 'center' justifyContent 'center' marginVertical 10 const color '#74B3CE' const ); expect(component.children(View).props('style').style).toMatchObject( transparentContainer, ); expect( component.children(View).children(Text).props('style').style, ).toMatchObject(transparentTitle); }); }); < /> Button transparent We use the to check if our style objects are correct. .toMatchObject Finally, we test by running npm run test Our test cases pass, yeee! 😝 Conclusion Testing is like our best friend, saving us from a lot of troubles. Testing our code prevents us from pushing breaking changes to production, forces us to write quality code, serves as a form of documentation, find bugs early, and a lot of other advantages. Resources For further readings and API references, check out the links below: Jest · 🃏 Delightful JavaScript Testing Testing · React Native Testing React Native Apps · Jest Also published at: https://medium.com/react-native-nigeria/getting-started-with-unit-testing-in-react-native-1fb2d0add259 Lead Photo by on Alvaro Reyes Unsplash