How to test if axios instance is called? - javascript

I'm trying to test if the axios instance "myApi" is being called
function code
const myApi = axios.create({
baseURL
})
async function auth () {
const request = await myApi.post('/authorization', {
email,
password
})
return request
}
how can I access the "myApi" instance in the test?

Related

Jest Mock changes to undefined from one line to another

I want to test my AWS Lambda functions written in typescript. The problem is that I'm mocking a service, which initially works fine and has all expected functions, but from one line to the other it turns to undefined, even though in the console.log right before it is defined.
My lambda function:
export const changePassword = LambdaUtils.wrapApiHandler(
async (event: LambdaUtils.APIGatewayProxyEvent, context: Context) => {
const accessToken = event?.body?.accessToken;
const previousPassword = event?.body?.previousPassword;
const proposedPassword = event?.body?.proposedPassword;
// let authenticationService = Injector.getByName("AuthenticationService"); // I tried mocking this object but given the dependency injection it is always undefined
//Request
const authenticationService = new AuthenticationService(); // Here it is perfectly mocked
console.log("-> authenticationService", authenticationService); // Here it is also defined with all functions
const response = await authenticationService.changePassword(
accessToken,
previousPassword,
proposedPassword
); //Here authenticationService is undefined
console.log("response in auth_handler", response);
if (response?.statusCode === 200) {
return new LambdaUtilities().createHttp200Response(response);
}
}
);
My test component:
jest.mock("../../../controllers/auth.service");
const MockedAuthService = AuthenticationService as jest.Mock<AuthenticationService>;
.....
test(`Test successful response of changePassword Repo function"`, async () => {
const accessToken = "accessToken";
const previousPassword = "123456";
const proposedPassword = "654321";
const mockAuthService = new MockedAuthService() as jest.Mocked<AuthenticationService>;
console.log("-> mockAuthService", mockAuthService);
const event = {
body: {
accessToken,
proposedPassword,
previousPassword
}
};
const response = await changePassword(event, {}, {});
console.log("response", response);
expect(response).not.toBeNull();
});
Here are screenshots from a debug with PyCharm:

Jest mock function in window

I have a function inside the window that retrieves the axios, from there I make the request for my API. I'm trying to mock her and I can't
window.axios
In my helper:
module.exports = () => window.axios;
In my service:
const axios = require('myHelper')
async myFunc() {
return axios()({
url: `${myURL}/drafts`,
method: 'GET',
});
}
In my test file I try to mock and a console, but it comes as undefined.
const axios = require('helpers/axios');
jest.mock('helpers/axios');
console.log(axios())
I need to axios().get.mockResolvedValue(myMock)

How to mock a method inside Express router Jest test?

I'm trying to test a router in Node.js app with Jest + Supertest, but my router is making a call to service, which is calling the endpoint:
router.post('/login', async (req, res, next) => {
try {
const { username, password } = req.body;
// I WANT TO MOCK userService.getUserInfo FUNCTION, BECAUSE IT IS MAKING A POST CALL
const identity = await userService.getUserInfo(username, password);
if (!identity.authenticated) {
return res.json({});
}
const requiredTenantId = process.env.TENANT_ID;
const tenant = identity.tenants.find(it => it.id === requiredTenantId);
if (requiredTenantId && !tenant) {
return res.json({});
}
const userResponse = {
...identity,
token: jwt.sign(identity, envVars.getVar(envVars.variables.AUTH_TOKEN_SECRET), {
expiresIn: '2h',
}),
};
return res.json(userResponse);
} catch (err) {
return next(err);
}
});
This is my test that works well:
test('Authorized - respond with user object', async () => {
const response = await request(app)
.post('/api/user/login')
.send(users.authorized);
expect(response.body).toHaveProperty('authenticated', true);
});
this is how getUserInfo function looks like:
const getUserInfo = async (username, password) => {
const identity = await axios.post('/user', {username, password});
return identity;
}
but it executes the method getUserInfo inside a router and this method is making a REST call - I want to mock this method in order to avoid REST calls to other services.
How it could be done?
I've found a mockImplementation function in Jest docs https://jestjs.io/docs/en/mock-function-api.html#mockfnmockimplementationfn
but how I can mock func inside a supertest testing?
You can use jest's auto mocking at the top of your test
like so:
jest.mock('./path/to/userService');
// and include it as well in your test
const userService = require('./path/to/userService');
it will generate a mock of the entire module and every function will be replaced with jest.fn() with no implementation
and then depending on the userService if it's just an object it's getUserInfo method will be a jest.fn() and you can set it's return value like this:
// resolved value as it should return a promise
userService.getUserInfo.mockResolvedValue(mockIdentity);
and the mockIdentity will have to look something like this:
const mockIdentity = {
authenticated: true,
tenants: [
{
id: "x12",
mockInfo: "mock-info-value"
}
],
mother: "Superwoman",
father: "Superman"
})
}

How do I mock constructor state initialisation with Jest

New to node.js. I am writing a JS API client that wraps the underlying axios library. In the unit tests I am mocking axios using Jest.
In the constructor of my API class I pass in a URL, and use the axios.create function to create a custom instance of axios and bind it to the the client property.
The problem arises when I mock the axios dependency with jest.mock('axios') - A TypeError is being thrown in the test when an attempt is made to call axios.get:
TypeError: Cannot read property `get` of undefined
I understand why this is happening, but I've not found a way to enable me to mock axios and not have the client field be undefined. Is there a way to get around this, other than injecting axios through the constructor?
Client code and test below:
client.js
jest.mock("axios");
const axios = require("axios");
const mockdata = require("./mockdata");
const ApiClient = require("../../../src/clients/apiclient");
const BASE_URL = "https://www.mock.url.com"
const mockAxiosGetWith = mockResponse => {
axios.get.mockResolvedValue(mockResponse);
};
test("should make one get request", async () => {
mockAxiosGetWith(MOCK_RESPONSE)
// the client field in apiclient is undefined
// due to the jest module mocking of axios
const apiclient = new ApiClient.AsyncClient(BASE_URL);
// TypeError: Cannot read property `get` of undefined
return await apiclient.get("something").then(response => {
expect(axios.get).toHaveBeenCalledTimes(1);
});
});
client.test.js
const axios = require("axios");
const getClient = (baseUrl = null) => {
const options = {
baseURL: baseUrl
};
const client = axios.create(options);
return client;
};
module.exports = {
AsyncClient: class ApiClient {
constructor(baseUrl = null) {
this.client = getClient(baseUrl);
}
get(url, conf = {}) {
return this.client
.get(url, conf)
.then(response => Promise.resolve(response))
.catch(error => Promise.reject(error));
}
}
};
You need to mock axios so it will return an object which holds the create function which should return the object with the get
import axios from 'axios'
jest.mock('axios', () => ({create: jest.fn()}))
test("should make one get request", async () => {
const get = jest.fn(()=>Promise.resolve(MOCK_RESPONSE))
axios.create.mockImplementation(()=>({get}))
const apiclient = new ApiClient.AsyncClient(BASE_URL);
await apiclient.get("something")
expect(get).toHaveBeenCalledTimes(1);
});

How to test a public async function inside Class using Jest in a ReactJS/Typescript app

Property 'getUsersTotalPayout` does not exist on type typeof PayoutApi
My Class:
import { bind } from 'decko';
import BaseApi from './Base';
import * as NS from './types';
class PayoutApi extends BaseApi {
#bind
public async getUsersTotalPayout(userId: string): Promise<number> {
const params: NS.IGetUsersTotalPayoutRequest = { userId };
const response = await this.actions.get<{ payout: number }>(
'/api/get-total-payout',
params,
);
return response.data.payout;
}
}
export default PayoutApi;
The test file:
import PayoutApi from './LiquidityPool';
const endpoint = '/api/get-total-payout';
const userId = 'foo';
jest.mock(endpoint, () => ({
getUsersTotalPayout: jest.fn(() => Promise.resolve({ data: { payout: 100.21 } }))
}));
describe('API: getUsersTotalPayout', () => {
it('should make a request when we get images', () => {
// const testApi = new PayoutApi();
expect(PayoutApi.getUsersTotalPayout(userId)).toHaveBeenCalledWith(endpoint, 'GET');
});
});
Getting that error on expect(PayoutApi.getUsersTotalPayout).toHaveBeenCalledWith(endpoint, 'GET');
You are currently trying to call method on the class. Since it is not static you should instantiate object of class first.
let api = new PayoutApi();
expect(api.getUsersTotalPayout(userId).....)
since jest.mock mocks module not endpoint or XHR request your test will try sending live request to /api/get-total-payout. For handling that it's needed to know what XHR wrapper do you use. Say for fetch() there is nice wrapper-mocker and libraries like axios also have their equivalence.
As for test itself. It does not work if you call a method and make expect on its result. It should be running method that must call server and then checking for mocked XHR if it has been called with valid parameters:
api.getUsersTotalPayout(userId);
expect(fetch_or_other_wrapper_for_mocking_xhr.get_last_request_method()).toEqual('get', endpoint, userId)

Categories

Resources