How to Mock jQuery AJAX Requests in Testing
Mocking jQuery AJAX calls is essential for creating reliable, fast,
and isolated unit tests without relying on an active backend server.
This article covers the most effective approaches to intercept and
simulate $.ajax, $.get, and
$.post requests during testing. You will learn how to mock
network activity using popular testing tools like Sinon.JS, Jest, and
Jasmine, allowing you to test both successful responses and error states
deterministically.
1. Using Sinon.JS Fake Server
Sinon.JS is one of the most widely used libraries for mocking network
requests in JavaScript. It provides a fake server that seamlessly
intercepts XMLHttpRequest calls generated by jQuery.
Installation
npm install --save-dev sinonImplementation
Set up the fake server before running the test, specify the expected response, and restore the native behavior in the cleanup phase.
describe('jQuery AJAX with Sinon.JS', () => {
let server;
beforeEach(() => {
// Intercept native XHR calls
server = sinon.fakeServer.create();
server.autoRespond = true;
});
afterEach(() => {
// Restore native behavior
server.restore();
});
it('fetches user data successfully', (done) => {
const mockData = { id: 1, name: 'Jane Doe' };
// Define endpoint, status code, headers, and body
server.respondWith(
'GET',
'/api/user',
[200, { 'Content-Type': 'application/json' }, JSON.stringify(mockData)]
);
$.ajax({
url: '/api/user',
method: 'GET',
dataType: 'json',
success: (data) => {
expect(data.name).toBe('Jane Doe');
done();
}
});
});
});2. Mocking
$.ajax Directly with Jest
If you are using Jest, you can directly spy on and mock the
$.ajax method without requiring external server-mocking
libraries.
Implementation
Use jest.spyOn to intercept the function call and return
a resolved or rejected promise or trigger the appropriate callbacks.
describe('jQuery AJAX with Jest', () => {
afterEach(() => {
jest.restoreAllMocks();
});
it('resolves with mocked data using promises', async () => {
const mockResponse = { status: 'success', data: [1, 2, 3] };
// Spy on $.ajax and return a resolved Deferred-like promise
jest.spyOn($, 'ajax').mockImplementation(() => {
return $.Deferred().resolve(mockResponse).promise();
});
const result = await $.ajax({ url: '/api/items', method: 'GET' });
expect($.ajax).toHaveBeenCalledWith(
expect.objectContaining({ url: '/api/items' })
);
expect(result.data).toEqual([1, 2, 3]);
});
it('handles request failure', (done) => {
const errorResponse = { statusText: 'Not Found' };
jest.spyOn($, 'ajax').mockImplementation((options) => {
if (options.error) {
options.error(errorResponse, 'error', 'Not Found');
}
return $.Deferred().reject(errorResponse).promise();
});
$.ajax({
url: '/api/missing',
error: (xhr, status, error) => {
expect(status).toBe('error');
expect(error).toBe('Not Found');
done();
}
});
});
});3. Using Jasmine Ajax
(jasmine-ajax)
For projects tested with Jasmine, the official
jasmine-ajax plugin provides built-in utilities to capture
and reply to requests.
Installation
npm install --save-dev jasmine-ajaxImplementation
Initialize the mock network interface using
jasmine.Ajax.install() and define the response using
respondWith.
describe('jQuery AJAX with Jasmine', () => {
beforeEach(() => {
jasmine.Ajax.install();
});
afterEach(() => {
jasmine.Ajax.uninstall();
});
it('simulates a server response', () => {
const callback = jasmine.createSpy('callback');
$.get('/api/status', callback);
const request = jasmine.Ajax.requests.mostRecent();
expect(request.url).toBe('/api/status');
request.respondWith({
status: 200,
contentType: 'application/json',
responseText: '{"online": true}'
});
expect(callback).toHaveBeenCalledWith({ online: true }, 'success', jasmine.any(Object));
});
});Best Practices for Mocking AJAX
- Clean Up State: Always restore or uninstall mocks
in an
afterEachblock to prevent mocked responses from leaking into subsequent tests. - Test Failure Scenarios: Mock non-200 HTTP status
codes (such as
400,401, and500) and network timeouts to ensure your application handles edge cases gracefully. - Assert Payloads: Verify that outgoing payload parameters, headers, and HTTP methods match the requirements of your API.