使用 Jest 测试来自 react-router v4 的 Link
Using Jest to test a Link from react-router v4
我正在使用 jest
来测试带有来自 react-router v4 的 <Link>
的组件。
我收到一条警告,提示 <Link />
需要来自 react-router <Router />
组件的上下文。
如何在测试中模拟或提供路由器上下文? (基本上我该如何解决这个警告?)
Link.test.js
import React from 'react';
import renderer from 'react-test-renderer';
import { Link } from 'react-router-dom';
test('Link matches snapshot', () => {
const component = renderer.create(
<Link to="#" />
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
测试时的警告是运行:
Warning: Failed context type: The context `router` is marked
as required in `Link`, but its value is `undefined`.
您可以使用 StaticRouter 在测试中包装您的组件,以将路由器上下文获取到您的组件中:
import React from 'react';
import renderer from 'react-test-renderer';
import { Link } from 'react-router-dom';
import { StaticRouter } from 'react-router'
test('Link matches snapshot', () => {
const component = renderer.create(
<StaticRouter location="someLocation" context={context}>
<Link to="#" />
</StaticRouter>
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
看看反应路由器docs about testing
我遇到了同样的问题,使用 StaticRouter
仍然需要 context
,它需要更多配置才能在我的测试中使用,所以我最终使用了 MemoryRouter
运行良好,没有任何问题。
import React from 'react';
import renderer from 'react-test-renderer';
import { MemoryRouter } from 'react-router-dom';
// SampleComponent imports Link internally
import SampleComponent from '../SampleComponent';
describe('SampleComponent', () => {
test('should render', () => {
const component = renderer
.create(
<MemoryRouter>
<SampleComponent />
</MemoryRouter>
)
.toJSON();
expect(component).toMatchSnapshot();
});
});
我的测试是这样的:
import * as React from 'react'
import DataBaseAccout from '../database-account/database-account.component'
import { mount } from 'enzyme'
import { expect } from 'chai'
import { createStore } from 'redux'
import reducers from '../../../reducer/reducer'
import { MemoryRouter } from 'react-router'
let store = createStore(reducers)
describe('mount database-account', () => {
let wrapper
beforeEach(() => {
wrapper = mount(
< MemoryRouter >
<DataBaseAccout store={store} />
</MemoryRouter >
)
})
afterEach(() => {
wrapper.unmount()
wrapper = null
})
})
但是不知道为什么MemoryRouter可以解决这个问题。
以上解决方案有一个共同的默认缺陷:
无法访问您的组件实例! 因为 MemoryRouter
或 StaticRouter
组件包装了您的组件。
所以解决这个问题最好的办法就是mock一个router context,代码如下:
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
describe('YourComponent', () => {
test('test component with react router', () => {
// mock react-router context to avoid violation error
const context = {
childContextTypes: {
router: () => void 0,
},
context: {
router: {
history: createMemoryHistory(),
route: {
location: {
hash: '',
pathname: '',
search: '',
state: '',
},
match: { params: {}, isExact: false, path: '', url: '' },
}
}
}
};
// mount component with router context and get component's instance
const wrapper = mount(<YourComponent/>, context);
// access your component as you wish
console.log(wrapper.props(), wrapper.state())
});
beforeAll(() => {
configure({ adapter: new Adapter() });
});
});
我正在使用 jest
来测试带有来自 react-router v4 的 <Link>
的组件。
我收到一条警告,提示 <Link />
需要来自 react-router <Router />
组件的上下文。
如何在测试中模拟或提供路由器上下文? (基本上我该如何解决这个警告?)
Link.test.js
import React from 'react';
import renderer from 'react-test-renderer';
import { Link } from 'react-router-dom';
test('Link matches snapshot', () => {
const component = renderer.create(
<Link to="#" />
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
测试时的警告是运行:
Warning: Failed context type: The context `router` is marked
as required in `Link`, but its value is `undefined`.
您可以使用 StaticRouter 在测试中包装您的组件,以将路由器上下文获取到您的组件中:
import React from 'react';
import renderer from 'react-test-renderer';
import { Link } from 'react-router-dom';
import { StaticRouter } from 'react-router'
test('Link matches snapshot', () => {
const component = renderer.create(
<StaticRouter location="someLocation" context={context}>
<Link to="#" />
</StaticRouter>
);
let tree = component.toJSON();
expect(tree).toMatchSnapshot();
});
看看反应路由器docs about testing
我遇到了同样的问题,使用 StaticRouter
仍然需要 context
,它需要更多配置才能在我的测试中使用,所以我最终使用了 MemoryRouter
运行良好,没有任何问题。
import React from 'react';
import renderer from 'react-test-renderer';
import { MemoryRouter } from 'react-router-dom';
// SampleComponent imports Link internally
import SampleComponent from '../SampleComponent';
describe('SampleComponent', () => {
test('should render', () => {
const component = renderer
.create(
<MemoryRouter>
<SampleComponent />
</MemoryRouter>
)
.toJSON();
expect(component).toMatchSnapshot();
});
});
我的测试是这样的:
import * as React from 'react'
import DataBaseAccout from '../database-account/database-account.component'
import { mount } from 'enzyme'
import { expect } from 'chai'
import { createStore } from 'redux'
import reducers from '../../../reducer/reducer'
import { MemoryRouter } from 'react-router'
let store = createStore(reducers)
describe('mount database-account', () => {
let wrapper
beforeEach(() => {
wrapper = mount(
< MemoryRouter >
<DataBaseAccout store={store} />
</MemoryRouter >
)
})
afterEach(() => {
wrapper.unmount()
wrapper = null
})
})
以上解决方案有一个共同的默认缺陷:
无法访问您的组件实例! 因为 MemoryRouter
或 StaticRouter
组件包装了您的组件。
所以解决这个问题最好的办法就是mock一个router context,代码如下:
import { configure, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
describe('YourComponent', () => {
test('test component with react router', () => {
// mock react-router context to avoid violation error
const context = {
childContextTypes: {
router: () => void 0,
},
context: {
router: {
history: createMemoryHistory(),
route: {
location: {
hash: '',
pathname: '',
search: '',
state: '',
},
match: { params: {}, isExact: false, path: '', url: '' },
}
}
}
};
// mount component with router context and get component's instance
const wrapper = mount(<YourComponent/>, context);
// access your component as you wish
console.log(wrapper.props(), wrapper.state())
});
beforeAll(() => {
configure({ adapter: new Adapter() });
});
});