Angular / Jasmine Tip: Getting at the Real Error Message Behind XMLHttpRequest

September 04, 2020
Cover Image

Has this ever happened to you? You're working on the code for your Angular app. And since you're an amazing developer, you're also writing test specs using Jasmine. You want to run your tests so you pop down to the terminal and type ng test to execute your tests.

You expect to have everything run and pass but instead you get a half-zillion test failures and lots of them have a weird and completely unhelpful error message:

Uncaught NetworkError: Failed to execute 'send' on 'XMLHttpRequest'

Bad Karma: Tons of failed test specs with the XMLHttpRequest error

WHAT -- IS -- GOING -- ON?!?!?!?!

It's Not the Real Error

The problem here is that the real error message is hidden. I don't remember where I learned this trick but it's helped me out a bunch of times in my Jasmine tests for Angular.

Instead of running your tests with the ng test command, use ng test --source-map=false.

The Real Error Revealed

Ok. So this time, you head to the command prompt (shell, terminal, etc) and you run ng test --source-map=false.

This time you'll get a much better error. In this case, the error message is "NullInjectorError: R3InjectorError(DynamicTestModule)[FormBuilder -> FormBuilder]: NullInjectorError: No provider for FormBuilder!"

A much better error message

It's Almost Always a Dependency Problem

The underlying problem is almost always some kind of missing dependency that's causing the Angular dependency injection / IoC framework to panic.

So when our typescript or javascript code gets executed, it goes through something like a compilation process that take the human-readable code and turns it into something that can be executed efficiently. In the case of typescript, there's an extra step and the code gets 'transpiled' into javascript before execution. The source map is supposed to help us to debug our code by connecting the instructions that are being executed to the source code that inspired those instructions. If we didn't have that, it would be a whole lot harder to debug our apps.

My theory on why ng test --source-map=false helps in these weirdo error cases is that because of the type of problem (dependency injection problems), the source map thinks that the problem is in the dependency injection framework rather than in your code that configures the dependencies.

So. By turning off the source map generation, you get the real error.

(Disclaimer: that theory could be wildly wrong...but it makes sense to me.)

A Little More About My Error

So this blog post is about how to get at the real error message but while I'm here, I figure I might as well tell you how I fixed the real error, too. Like I said, it's almost always a dependency problem. Lately, I've been working on converting a bunch of template-driven angular forms over to reactive forms. This means that in my Jasmine specs, that I need to update the imports directive to reference ReactiveFormsModule instead of FormsModule.

To fix this, I need to get to the call to TestBed.configureTestingModule and find the FormsModule import. Change this over to be ReactiveFormsModule and voila! -- the problem is fixed.

The import for FormsModule that needs to be modified

Change the import to ReactiveFormsModule

Summary

In short, there's something about dependency import problems in Jasmine tests for Angular that sometimes causes the real errors to be eaten. So if you find yourself wondering about why you're getting that strange XMLHttpRequest error, try running your test suite without source maps. The command to do that is ng test --source-map=false.

I hope this helps.

-Ben

-- Looking for help with Angular and/or Angular testing? We can help. Drop us a line at info@benday.com.