I'm trying to send a CORS POST request to my API and it throws a TypeError every time I use the 'Authorization' header. The request doesn't even get sent, so the server is not involved. But this only happens in my tests. When I try it in Chrome it works just fine.
Here is the function that I'm testing:
export const postNewEmployee = formData => {
return fetch('http://localhost:3003', {
method: 'POST',
headers: {
'Authorization': 'Bearer test123',
'Content-Type': 'application/json'
},
body: JSON.stringify(formData)
})
.then(response => response)
.catch(error => {
throw error;
});
};
And its test:
import * as API from './api';
describe('postNewEmployee', () => {
it('posts the form data asynchronously', () => {
let formData = {
employee: {
name: 'Test Person',
email: 'test@person.nu',
address: 'an adress 123'
}
};
return API.postNewEmployee(formData)
.then(json => {
expect(json.status).toEqual(201);
}).catch(error => {
console.log(error);
});
});
});
The application is a react/redux app created with create-react-app, so I'm using Jest and JSDOM to test this. The thing is, if I comment out the Authorization header from the fetch()-call, it works fine. But if I add that header I get this:
TypeError: Cannot convert undefined or null to object
at Object.getRequestHeader (/Users/johanh/Kod/react-app/node_modules/react-scripts/node_modules/jsdom/lib/jsdom/living/xhr-utils.js:20:23)
at setDispatchProgressEvents (/Users/johanh/Kod/react-app/node_modules/react-scripts/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:909:38)
at XMLHttpRequest.send (/Users/johanh/Kod/react-app/node_modules/react-scripts/node_modules/jsdom/lib/jsdom/living/xmlhttprequest.js:700:11)
at /Users/johanh/Kod/react-app/node_modules/react-scripts/node_modules/whatwg-fetch/fetch.js:429:11
at Object.<anonymous>.self.fetch (/Users/johanh/Kod/react-app/node_modules/react-scripts/node_modules/whatwg-fetch/fetch.js:373:12)
at Object.<anonymous>.exports.postNewEmployee.formData [as postNewEmployee] (/Users/johanh/Kod/react-app/src/api/api.js:20:10)
at Object.it (/Users/johanh/Kod/react-app/src/api/api.test.js:75:16)
at Object.<anonymous> (/Users/johanh/Kod/react-app/node_modules/react-scripts/node_modules/jest-jasmine2/build/jasmine-async.js:42:32)
at attemptAsync (/Users/johanh/Kod/react-app/node_modules/react-scripts/node_modules/jest-jasmine2/vendor/jasmine-2.4.1.js:1919:24)
at QueueRunner.run (/Users/johanh/Kod/react-app/node_modules/react-scripts/node_modules/jest-jasmine2/vendor/jasmine-2.4.1.js:1874:9)
And as I said, this only happens in the test. In the browser it works fine.
I feel like I'm missing something obvious here, but I just can't see it. I've looked in the fetch spec and the jsdom documentation, but to no avail. Any ideas?
Normally you should not make real requests in a unit test. The best way to handle this is to use a mock instead of the real fetch
implementation.
I assume you are using the JS implementation of fetch
. So you can set fetch
to what ever you want in your test.
import * as API from './api';
describe('postNewEmployee', () => {
it('posts the form data asynchronously', () => {
// set fetch to a mock that always returns a solved promise
const fetch = jest.fn((url, options) => return Promise.resolve({status: 201}))
global.fetch = fetch;
let formData = {
employee: {
name: 'Test Person',
email: 'test@person.nu',
address: 'an adress 123'
}
};
//test that fetch was called with the correct parameters
expect(fetch.mock.calls[0][0]).toBe('http://localhost:3003')
expect(fetch.mock.calls[0][1]).toEqual(formData)
return API.postNewEmployee(formData)
.then(json => {
expect(json.status).toEqual(201);
}).catch(error => {
console.log(error);
});
});
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.