1. 27
    Use Karma for Unit Testing with Webpack
    4m 53s
⚠️ This lesson is retired and might contain outdated information.

Use Karma for Unit Testing with Webpack

Kent C. Dodds
InstructorKent C. Dodds
Share this video with your friends

Social Share Links

Send Tweet
Published 8 years ago
Updated 2 years ago

When writing tests run by Karma for an application that’s bundled with webpack, it’s easiest to integrate webpack and Karma directly together. In this lesson we’ll see how to utilize the karma-webpack plugin and reuse our existing webpack configuration to preprocess our test files with webpack.

[00:00] We want to be able to actually import our controller and start unit testing it. If I were to try that import controller from controller, and go ahead and run the test, we're going to get this Uncaught SyntaxError Unexpected token import.

[00:16] That's because the browser doesn't understand the import statement. Even if we were to write this using require statements instead, the browser still wouldn't be able to understand that because it has no way of resolving those required statements. That's where Webpack comes into play.

[00:32] What we need to do is tell Karma to pre-process all of our test files with Webpack, so that these import statements are resolved, and the bundle for that test file is delivered to the browser to rerun for our test.

[00:45] To do this, we're simply going to install as a dev dependency the karma-Webpack plugin. With that, we'll go our package.json just to verify quickly that we have the karma-Webpack plugin installed here. Then, we can go to our Karma config. Here, we're going to utilize this Webpack plugin for Karma. It'll bundle each of our test.

[01:06] For Karma, Webpack is what's called a pre-processor. We basically want to pipe all of our test files through Webpack, so Webpack can bundle these and prepare them for delivery to the browser. Then, the browser will take this bundle and run it, which will run our test.

[01:21] We're going to start out by adding a pre-processor's object here. In here, the key is going to be the glob that we want to have pre-processed. In our case, we want all of these files to be pre-processed.

[01:34] I'm going to extract into a variable called file glob. We'll put that up here. We'll add that as our key. The value will be an array of the pre-processors we want to have these files run through, which will be Webpack in our case.

[01:50] If we run our test, we're going to see that it still is not working. We're still getting the unexpected token import. That's because Webpack needs to know what configuration it needs to use to bundle our files.

[02:02] The way that we tell Webpack what configuration to use is by using a Webpack property. Here, it will take an object with our configuration. We don't want to duplicate our configuration both in our Karma config and our Webpack config.

[02:15] We can actually require this, because it's a regular node module. It exports a function that accepts an ENV object. If we simply require this and then invoke that function, it will return us the Webpack configuration that we're using for our app, which incidentally will work fine for Karma.

[02:34] Let's go ahead and do that here. We'll have a Webpack config that is equal to require of the Webpack config file. We'll invoke that with a Webpack ENV, which will simply be an object with test as true.

[02:51] We're not actually using test as an ENV property in our Webpack config file right now. It's totally a reasonable thing that we could do in the future. For good measure, we'll do that now.

[03:02] We'll take this Webpack configuration. We'll assign to the Webpack property. If we go ahead and run npm t, we'll see that this actually now runs. We'll see a little bit of output from Webpack here and eslint. Our tests are running now.

[03:18] Let's go ahead and update our test to actually utilize the controller constructor that we're importing. We'll simply expect that the controller constructor exists for now.

[03:27] With that, if we run npm t to run our test, we're going to see this output from Webpack. That can get annoying, especially when you're in watch mode. We're going to disable that in our Karma config.

[03:41] We go into our current config here. We can add Webpack [inaudible] . This will simply be an object that has a no info property as true.

[03:52] If we run our test again, we see that we don't get that output from Webpack. The output that we do see is relevant to what we're interested in seeing.

[04:01] Let's go ahead and review. The first thing that we had to do is install the Karma Webpack plugin so that we can use that as a pre-processor for our test. Then, we went into our Karma configuration. We added a pre-processor using the same file glob that we use for our files. We defined the pre-processor to be Webpack for those files.

[04:23] We got our Webpack configuration from our Webpack config file, where we passed in a Webpack ENV to that function to get our Webpack config. We assigned that to the Webpack property in our configuration. We went ahead and updated our controller test to utilize the controller import.

[04:41] Finally, to save ourselves from a little bit of noise in the output, we added a Webpack middleware here with a no info property set to true. That's how you add Webpack pre-processing to your Karma configuration.

samuel
samuel
~ 8 years ago

Any suggestions on how to handle the CommonsChunkPlugin? I am getting an error webpackJsonp in my testing file.

Thanks

Kent C. Dodds
Kent C. Doddsinstructor
~ 8 years ago

Hey! Actually, you might like my other lessons about Webpack. Specifically this one. Basically you disable CommonsChunkPlugin in test mode. I also recommend you give this a look to help make that easier :)

Good luck!

Carlos
Carlos
~ 7 years ago

Things to note if dealing with typescript like me:

  1. Take account for the Mime property in karma.conf.ts for typescript files or the test won't even run (because the karma browser doesn't recognize the mime type), for example like:
const karmaConfig = (config) => {
  config.set({
    ...
    mime : {
      'text/x-typescript': [
        'ts',
        'tsx'
      ]
    },
    ...
  1. Remember when using the globs, that typescript files have ts extension.
Markdown supported.
Become a member to join the discussionEnroll Today