fetch-mock calls the actual API instead of mocking the request - javascript

Given this code:
const fetch = require('isomorphic-fetch')
module.exports = function suggestions (...args) {
// some error handling code
return fetch(MY_ENDPOINT)
}
I have found that when using fetch-mock like this:
require('isomorphic-fetch')
const fetchMock = require('fetch-mock/es5/server')
fetchMock.mock(MY_ENDPOINT, [{}, {}])
describe('My spec', () => {
it('fakes a request to my endpoint', async () => {
const myData = await myCode(...args) // calls fetch with my endpoint
expect(myData).toEqual([{}, {}])
})
})
I would expect the mock to give me the response I set up which is [{},{}], instead it calls the real API and returns the response from it.
Also, if I try to use fetch-mock instead of fetch-mock/es5/server I get the error:
/Users/localuser/lendi/ldp-domain-integration/node_modules/fetch-mock/src/lib/fetch-handler.js:57
FetchMock.generateResponse = async function (response, url, opts) {
^^^^^^^^
SyntaxError: Unexpected token function
I use jest with babel and babel-jest along with node v6.13.0.

The reason for the Syntax error is that async functions are not supported in Node version 6.
Try updating Node to the latest version.

Related

Jest / React-test-renderer testing async promise based calls

I am trying to test some api calls in Jest, however the test is failing as the api call is dependent on another call to complete first, so the returned value is empty as opposed to what should be in there. I am using react-query for the api calls. Or is there a better or other way to test async calls? I am using MSW also, to intercept the api calls.
Async call
const getApi = async (): Promise<any> => {
const response = await axios.get(`https://www.xxxxx`).then(res => res.data);
return response;
}
test
const queryClient = new QueryClient()
describe('Comp1 tests', (): void => {
beforeEach(() => {
jest.useFakeTimers();
});
it('Should give correct response with render', async () => {
renderWithQueryClient(<QueryClientProvider client={queryClient}><Comp1 /></QueryClientProvider>);
expect(await screen.findByTestId('main-header')).toBeInTheDocument();
});
});
I get:
Unable to find an element by: [data-testid="main-header"]

How to stub promise.all in sinon

I have a function which has 2 APi calls. Iam destructuring the response and sending each response to different functions to perform some operation. I need to write test case to make API call., fetch response & pass it to respective functions.
This is my code
async _fetchComponentDetails() {
const [firstResponse, secondResponse] = await Promise.all([
this._getfirstApiResponse(param1, param2),
this._getSecondApiResponse(param1, param2),
]);
this.formatFirstApiResult = await componentSerives.formatFirstResponseData(firstResponse);
this.formatSecondApiResult = await componentSerives.formatSecondResponseData(secondResponse);
}
This is my Service call
async _getfirstApiResponse(param1, param2) {
const url = 'api/firstApi';
const firstResponse = await componentSerives.fetchApiDetails(url, param1, param2);
return firstResponse;
}
async _getSecondApiResponse(param1, param2) {
const url = 'api/secondApi';
const secondResponse = await componentSerives.fetchApiDetails(url, param1, param2);
return secondResponse;
}
This is the Test case I written
it('it should make make API calls for first and second',async () => {
sinon.stub(componentSerives, 'fetchApiDetails').resolves(bannerResponse);
});
The issue iam facing is., I dont know how to send both first & second APi response in resolves();
on passing it as an array of objects like below., I see firstResponse & secondResponse loading in both objects.
[{firstResponse, secondResponse}]
can you help me how to stub both the APis and assign it to different responses in destructuring?
You are stubbing the wrong thing, according to your own test:
it('it should make make API calls for first and second',async () => {
If you are testing fetchApiDetails you cannot stub that function out. That makes no sense! Then you would just be testing your own stub.
What you need to stub out or inject, are its dependencies: _getfirstApiResponse and _getSecondApiResponse. Stub those out simply by having them just resolve some value:
const firstResponse = 42;
const secondResponse = -42;
sinon.replace(componentSerives, '_getfirstApiResponse', sinon.fake.resolves(firstResponse));
sinon.replace(componentSerives, '_getSecondApiResponse', sinon.fake.resolves(secondResponse ));
await componentSerives.fetchApiDetails();
assertEquals(componentSerives.formatFirstApiResult, "Result: 42");
assertEquals(componentSerives.formatSecondApiResult, "Result: -42");

Testing a Jest method that has multiple promises

I am attempting to write a test for a service in my app.
async post(url, params, headers) {
const csrfToken = await this.getCsrfToken().then(res => res.data);
headers.headers['X-CSRF-TOKEN'] = csrfToken;
// console.log(params);
return this.http.post(url, params, headers);
}
The issue I am encountering is I am getting an error that data is not defined. I believe this refers to the csrfToken call (which is just another API call to get this token to append to the header).
I'm not entirely sure how to mock that constant inside jest so I can actually get to my post call. Is there an easy way in jest?
You shouldn't try to mock the constant, you should mock the getCsrfToken instead. Try something like:
import { getCsrfToken, post } from MyClass
it('should work', () => {
// mock method on your class
myMock = jest.fn()
myMock.mockReturnValueOnce(Promise.resolve({
data: {
fakeCsrf
}
})
MyClass.csrfToken = myMock
post('/test', {}, {})
expect(...);
});

How do I mock async fetches with jest?

I've been struggling to figure out how to properly test this code for days :(
const request = require('superagent');
const getDog = () => {
return request.get('https://dog.ceo/api/breeds/image/random');
};
it('resolves', () => {
// Expect mocked response
});
it('rejects', () => {
// Expect mocked response
});
In most cases, your code gets some value from API parses it and makes some stuff with it.
As a result, you don't want to make real API call and mock it instead.
There are a couple of ways to do it. One of the possible is to mock the only method on the superagent library.
// tell jest not to mock superagent because we'll mock the only method
jest.unmock('superagent');
const request = require('superagent');
const getDog = () => {
return request.get('https://dog.ceo/api/breeds/image/random');
};
it('resolves', () => {
// mock the get request to resolve object
request.get = jest.fn().mockResolvedValue({
message: 'Your message'
});
// Expect mocked response
expect.assertions(1);
return expect(getDog()).resolves.toEqual({
message: 'Your message'
});
});
it('rejects', () => {
// mock the get request to reject object
request.get = jest.fn().mockRejectedValue({
message: 'Your error'
});
// Expect mocked response
expect.assertions(1);
return expect(getDog()).rejects.toEqual({
message: 'Your error'
});
});
I used expect.assertions(1), there is a reason:
This is often useful when testing asynchronous code, in order to make
sure that assertions in a callback actually got called.
There are links that can help you:
mockFn.mockResolvedValue(value)
,
.rejects
One solution is to use a library such as nock or fetch-mock to mock out the HTTP response to your request.

supertest and checking DynamoDB before and after using await

I'd like to test my koa API routes using supertest and check what's in DynamoDB before and after to make sure that the end point did what was intended.
// app related
const pool = require('../../src/common/pool');
const app = require('../../server');
// for testing
const uuid = require('uuid');
const supertest = require('supertest');
// listen on port 40002
const request = supertest.agent(app.listen(4002));
describe('test', () => {
it.only('should', async (done) => {
debugger;
const id = uuid.v4().replace(/-/g, '');
await pool.add(id, 'data', 30);
return request
.get('/api/1')
.expect(204)
// .then(async (res) => {
// .then((res) => {
.end((res) => {
// still returns 'data' instead of 'dataNew' after the route is hit
const record = await pool.get(id);
debugger;
done();
});
});
});
In the code above, I'm creating a record in the db, then I hit the end point, and I tried a then() and an end() chained function to check the db once again. The end point will just data to dataNew and in the then() function, it still returns the original data.
Any ideas on how I can verify the new record in the db ?
References:
Supertest: Verify database after request - In TLDR at the bottom, the solution was to use co. I tried this and had issues probably cause I'm using await instead of generators.
The above was fixed by chaining the pool.add() which returns a promise, to the supertest request and then awaiting the record to verify it. Sometimes it still gets the record too quickly because the pool.update() method is not awaited within the end point that request is hitting.
describe('test', () => {
it.only('should', async () => {
const id = uuid.v4().replace(/-/g, '');
await pool.add(id, 'data', 30).then(() => {
return request
.get('/api/1')
.expect(204)
// check custom headers
//.expect('pool-before', 'data')
//.expect('pool-after', 'dataModified')
.then(async (res) => {
const record = await pool.get(id);
debugger;
expect('dataModified').to.equal(record.fields.S);
});
});
});
});
The only other way I can think of is to check the value via a custom header, a delay, or use a mock.
Let me know if anyone has a better solution.

Categories

Resources