可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm developing a web app at work in React/Redux/Webpack and am now starting to integrate testing with Mocha.
I followed the instructions for writing tests in the Redux documentation, but now I have run into an issue with my webpack aliases.
For example, take a look at the imports section of this test for one of my action creators:
import expect from 'expect' // resolves without an issue
import * as actions from 'actions/app'; // can't resolve this alias
import * as types from 'constants/actionTypes'; // can't resolve this alias
describe('Actions', () => {
describe('app',() => {
it('should create an action with a successful connection', () => {
const host = '***************',
port = ****,
db = '******',
user = '*********',
pass = '******';
const action = actions.createConnection(host, port, db, user, pass);
const expectedAction = {
type: types.CREATE_CONNECTION,
status: 'success',
payload: { host, port, database, username }
};
expect(action).toEqual(expectedAction);
});
});
});
As the comments suggest, mocha isn't able to resolve my import statements when they are referencing aliased dependencies.
Because I'm still new to webpack, here's my webpack.config.js
:
module.exports = {
devtool: 'eval-source-map',
entry: [
'webpack-hot-middleware/client',
'./src/index'
],
output: {
path: path.join(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: '/static/'
},
resolve: {
extensions : ['', '.js', '.jsx'],
alias: {
actions: path.resolve(__dirname, 'src', 'actions'),
constants: path.resolve(__dirname, 'src', 'constants'),
/* more aliases */
}
},
plugins: [
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin()
],
module: {
loaders: [{
test: /\.js$/,
loaders: ['babel'],
exclude: /node_modules/,
include: __dirname
}]
}
};
Also, I'm using the command npm test
to run mocha, here's the script I'm using in my package.json
.
{
"scripts": {
"test": "mocha ./src/**/test/spec.js --compilers js:babel-core/register --recursive"
}
}
So here's where I get stuck. I need to include the aliases from webpack into mocha when it runs.
回答1:
Okay so I realized that everything I was aliasing was in the src/
directory, so I simply needed to modify my npm run test
script.
{
"scripts": {
"test": "NODE_PATH=./src mocha ./src/**/test/spec.js --compilers js:babel-core/register --recursive"
}
}
Probably won't work for everyone, but that solved my issue.
回答2:
You can also use a babel plugin I authored:
https://github.com/trayio/babel-plugin-webpack-alias
It will convert your aliased path to relative paths just by including a babel plugin to your .babelrc
.
回答3:
I also encountered the same problem, but with this plugin I solved it.
https://www.npmjs.com/package/babel-plugin-webpack-aliases
The execution command of your "mocha" is not reading the webpack.config.js
, so it can not resolve the alias.
By setting this plugin, consider webpack.config.js
when compiling with "babel-core/register". As a result, the alias will also be valid during testing.
npm i -D babel-plugin-webpack-aliases
and add this setting to .babelrc
{
"plugins": [
[ "babel-plugin-webpack-aliases", { "config": "./webpack.config.js" } ]
]
}
回答4:
Danny's answer is great. But my situation is a little bit different.
I used webpack's resolve.alias
to use all the files under src
folder.
resolve: {
alias: {
'-': path.resolve(__dirname, '../src'),
},
},
and use a special prefix for my own modules like this:
import App from '-/components/App';
To test code like this
I have to add a command ln -sf src test/alias/-
before mocha test and use the NODE_PATH=./test/alias
trick Danny camp up with. So the final script would be like this:
{
"scripts": {
"test": "ln -sf src test/alias/-; NODE_PATH=./test/alias mocha ./src/**/test/spec.js --compilers js:babel-core/register --recursive"
}
}
PS:
I used -
because beautifal charactors like @
or ~
are not safe enough. I found the answer for safe characters here
回答5:
I think I solved this problem. You should use 2 package: mock-require and proxyquire.
Assuming you have a js file like this:
app.js
import action1 from 'actions/youractions';
export function foo() { console.log(action1()) };
And your test code should write like this:
app.test.js
import proxyquire from 'proxyquire';
import mockrequire from 'mock-require';
before(() => {
// mock the alias path, point to the actual path
mockrequire('actions/youractions', 'your/actual/action/path/from/your/test/file');
// or mock with a function
mockrequire('actions/youractions', {actionMethod: () => {...}));
let app;
beforeEach(() => {
app = proxyquire('./app', {});
});
//test code
describe('xxx', () => {
it('xxxx', () => {
...
});
});
files tree
app.js
|- test
|- app.test.js
First mock the alias path by mock-require in before function, and mock your test object by proxyquire in beforeEach function.
回答6:
I had the exact same issue. It seems impossible to use webpack aliases in require.js or in node's require.
I ended up using mock-require in the unit tests and just replacing the paths manually, like this:
var mock = require('mock-require');
mock('actions/app', '../../src/actions/app');
mock-require is a good tool, because most likely you'd like to mock most of your dependencies anyway instead of using the actual scripts from src
.
回答7:
I assume you would have --require babel-register
in your mocha.opts
. You can use babel module resolver plugin https://github.com/tleunen/babel-plugin-module-resolver. This allows you to set alias in .babelrc, similar to your webpack alias:
{
"plugins": [
["module-resolver", {
"alias": {
"actions": "./src/actions",
"constants": "./src/constants"
}
}]
]
}
回答8:
To keep aliases in one place like config/webpack.common.js
resolve: {
alias: {
'~': path.resolve(__dirname, './../src/app')
}
}
then install babel-plugin-webpack-alias
npm i babel-plugin-webpack-alias --save-dev
then in .babelrc
put :
{
"presets": ["env"],
"plugins": [
["babel-plugin-webpack-alias", {
"config": "./config/webpack.common.js" // path to your webpack config
}]
]
}