2016-02-24 19 views
4

我在使用老版本的react-router时遇到了这个问题,我使用的解决方案如下:stubRouterContext +一种奇怪的访问方式该组件实例(使用参考:https://github.com/reactjs/react-router/issues/1140#issuecomment-113174774如何测试一个React组件,使用类似于反应路由器2.0中的Jest 0.8.x

我认为这将在未来改善,但我与反应路由器2.0击中相同的墙(我不是说这是一个反应路由器的问题,但因为它使用上下文,它会影响我的测试)。所以,我有一个使用上下文来推新州加入URL this.context.router.push(...)这是现在去 https://github.com/reactjs/react-router/blob/master/upgrade-guides/v2.0.0.md#programmatic-navigation

我告诉jest.dontMock('react-router')的方式,但我的测试失败与组件:

TypeError: Cannot read property 'push' of undefined

这是因为通过TestUtils.renderIntoDocument返回的实例将拥有:

context: Object { router: undefined }

现在,这里真正的问题是什么?它是不是?我敢肯定,我不是唯一一个遇到过这个问题的人,因为stubRouterContext它不再是反应路由器的official docs了,是否有任何广泛接受的解决方案?

我该如何让测试工作?基本上具有正确的上下文并能够访问由TestUtils.renderIntoDocument返回的组件实例中的所有内容。

我使用反应0.14.7,jest-cli 0.8.2和react-router 2.0。

+0

我有完全相同的问题。我放弃了使用测试来覆盖PageComponents,因为开销比它带来的价值更大,但我至少想要覆盖我的面包屑和导航。截至目前,我试图根据测试路线和位置对象呈现组件,并且TestUtils基于测试路线和位置对象,似乎是唯一可行的解​​决方案。你最终得到了什么? –

回答

0

下面是我已经结束了与我的上下文相关组件的安装(剥离下来为简单起见,当然):在单元测试中

// dontmock.config.js contains jest.dontMock('components/Breadcrumbs') 
// to avoid issue with hoisting of import operators, which causes 
// jest.dontMock() to be ignored 

import dontmock from 'dontmock.config.js'; 
import React from "react"; 
import { Router, createMemoryHistory } from "react-router"; 
import TestUtils from "react-addons-test-utils"; 

import Breadcrumbs from "components/Breadcrumbs"; 

// Create history object to operate with in non-browser environment 
const history = createMemoryHistory("/products/product/12"); 

// Setup routes configuration. 
// JSX would also work, but this way it's more convenient to specify custom 
// route properties (excludes, localized labels, etc..). 
const routes = [{ 
    path: "/", 
    component: React.createClass({ 
    render() { return <div>{this.props.children}</div>; } 
    }), 
    childRoutes: [{ 
    path: "products", 
    component: React.createClass({ 
     render() { return <div>{this.props.children}</div>; } 
    }), 
    childRoutes: [{ 
     path: "product/:id", 
     component: React.createClass({ 
     // Render your component with contextual route props or anything else you need 
     // If you need to test different combinations of properties, then setup a separate route configuration. 
     render() { return <Breadcrumbs routes={this.props.routes} />; } 
     }), 
     childRoutes: [] 
    }] 
    }] 
}]; 

describe("Breadcrumbs component test suite:",() => { 
    beforeEach(function() { 
    // Render the entire route configuration with Breadcrumbs available on a specified route 
    this.component = TestUtils.renderIntoDocument(<Router routes={routes} history={history} />); 
    this.componentNode = ReactDOM.findDOMNode(this.component); 
    this.breadcrumbNode = ReactDOM.findDOMNode(this.component).querySelector(".breadcrumbs"); 
    }); 

    it("should be defined", function() { 
    expect(this.breadcrumbNode).toBeDefined(); 
    }); 

    /** 
    * Now test whatever you need to 
    */ 
0

曾有同样的麻烦,不确定this.context.history

堆栈:0.14作出反应,反应路由器1.0,历史1.14,茉莉花2.4

解决了未来的方式。

对于反应路由器的历史,我使用“history/lib/createBrowserHistory”,它允许链接没有散列。这个模块是单身人士。这意味着一旦创建它可以通过你的所有应用程序使用。 所以我决定扔掉历史混入并直接使用历史,从单独的组件旁边道:

// history.js 

import createBrowserHistory from 'history/lib/createBrowserHistory' 
export default createBrowserHistory() 


// app.js 

import React from 'react' 
import ReactDOM from 'react-dom' 
import { Router, Route, IndexRoute } from 'react-router' 

import history from './history' 
import Main from './Main' 

const Layout = React.createClass({ 
    render() { 
    return <div>{React.cloneElement(this.props.children)}</div> 
    } 
}) 

const routes = (
    <Route component={Layout} path='/'> 
    <IndexRoute component={Main} /> 
    </Route> 
) 

ReactDOM.render(
    <Router history={history}>{routes}</Router>, 
    document.getElementById('my-app') 
) 


// Main.js 

import React from 'react' 
import history from './history' 

const Main = React.createClass({ 
    next() { 
    history.push('/next_page') 
    }, 

    render() { 
    return <button onClick={this.next}>{'Go to next page'}</button> 
    } 
}) 

export default Main 

就像一个魅力和可以很容易地进行测试。没有更多的mixin,没有更多的上下文(至少在这种特殊情况下)。我相信同样的方法可以用于标准的反应路由器浏览器历史,但没有检查。

相关问题