简体   繁体   English

单元测试无状态组件方法

[英]unit test stateless component method

I have this stateless component of react 我有这种无状态的反应成分

const Clock = () => {
    const formatSeconds = (totalSeconds) => {
        const seconds = totalSeconds % 60,
        minutes = Math.floor(totalSeconds / 60)

        return `${minutes}:${seconds}`
    }
    return(
        <div></div>
    )
}

export default Clock

How to test formatSeconds method? 如何测试formatSeconds方法?

I wrote this, which the test has failed. 我写了这个,测试失败了。

import React from 'react'
import ReactDOM from 'react-dom'
import expect from 'expect'
import TestUtils from 'react-addons-test-utils'

import Clock from '../components/Clock'

describe('Clock', () => {
    it('should exist', () => {
        expect(Clock).toExist()
    })

    describe('formatSeconds', () => {
        it('should format seconds', () => {
            const Clock = TestUtils.renderIntoDocument(<Clock />)
            const seconds = 615
            const expected = '10:15'
            const actual = Clock.formatSeconds(seconds)

            expect(actual).toBe(expected)
        })
    })
})

The first test passed but maybe there's some problem doing Clock.formatSeconds. 第一次测试通过但可能在执行Clock.formatSeconds时遇到了一些问题。

The component Clock is a function, which is invoked when the component is rendered. 组件Clock是一个函数,在呈现组件时调用该函数。 The method formatSeconds is defined inside the the Clock closure, and it's not a property of Clock , so you can't reach it from outside. 方法formatSecondsClock闭包内定义,并且它不是Clock的属性,因此您无法从外部访问它。

In addition, you are recreating the formatSeconds method on every render, and since the method doesn't actually use any prop in the scope, it's a bit wasteful. 此外,您在每个渲染上重新创建formatSeconds方法,并且由于该方法实际上并未使用范围中的任何prop,因此它有点浪费。 So, you can take the method out, and export it. 因此,您可以将该方法取出并导出。 You can also move it to another utility file, and import it, since it's not an integral part of Clock , and you might want to reuse it other places. 您也可以将其移动到另一个实用程序文件,然后导入它,因为它不是Clock的组成部分,您可能希望在其他地方重用它。

export const formatSeconds = (totalSeconds) => {
    const seconds = totalSeconds % 60,
    minutes = Math.floor(totalSeconds / 60)

    return `${minutes}:${seconds}`
}

const Clock = () => {
    return(
        <div></div>
    )
}

export default Clock

Now testing is easy as well: 现在测试也很简单:

import React from 'react'
import ReactDOM from 'react-dom'
import expect from 'expect'
import TestUtils from 'react-addons-test-utils'

import Clock, { formatSeconds } from '../components/Clock' // import formatSeconds as well

describe('Clock', () => {
    it('should exist', () => {
        expect(Clock).toExist()
    })

    describe('formatSeconds', () => {
        it('should format seconds', () => {
            const seconds = 615
            const expected = '10:15'
            const actual = formatSeconds(seconds) // use it by itself

            expect(actual).toBe(expected)
        })
    })
})

A little late to the party but I have two approaches I would like to share with you. 派对有点晚了,但我有两种方法可以跟你分享。 Right out of the box you cannot test private methods. 开箱即用,您无法测试私有方法。 Regardless if it is a stateless component or just a simple function with some private internals. 无论它是无状态组件还是仅具有一些私有内部的简单功能。 I have for one use the following approaches: 我有一个使用以下方法:

  1. Transform the stateless component into a class with public methods. 使用公共方法将无状态组件转换为类。 Yeah, this kinds beats the purpose. 是的,这种打败了目的。 But it is still an option. 但它仍然是一种选择。

  2. Keep the stateless component and declare the private methods as "static". 保留无状态组件并将私有方法声明为“静态”。

 const Button = onClick => { return <button onClick={Button.handleClick}> My Button </button>; } Button.handleClick = e => e.stopPropagation(); ReactDOM.render(<Button />, document.getElementById('root')); 
 <div id="root"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM