I no any idea how test updateTotal... if requestAxios is success return callback function updateTotal but how i spy that?
...methods:{
updateAll() {
const updateTotal = (request) => {
this.total = request.data.total
}
this.requestAxios(
'get',
'/api/',
{},
[updateTotal],
)
}
}...
requestAxios:
async requestAxios(
method = 'get',
url = '',
objSend = {},
successFunctions = [],
errorsFunctions = [],
formKey = 'form',
) {
let request = ''
if (method !== 'delete') {
request = await axios[method](url, objSend, this.headerRequestJson)
.then(response => this.responseRequestText(response))
.catch(errors => this.responseRequestText(errors.response));
} else {
request = await axios.delete(url, {
data: objSend,
headers: this.headerRequestJson.headers,
})
.then(response => this.responseRequestText(response))
.catch(errors => this.responseRequestText(errors.response));
}
if (request.status === 'success') {
// success callback fn
successFunctions.forEach((value) => {
value(request, formKey)
})
} else {
// errors callback fn
errorsFunctions.forEach((value) => {
value(request)
})
// adicionar erros nos campos
this.addErrors(request, formKey);
}
},
My attempt:
test('updateTotalFinancial: ', () => {
const update = jest.fn()
const response = {
data: {
total: 100,
},
}
const requestAxios = jest.fn(() => update(response))
const wrapper = shallowMount(ModalUnderwriting, {
store,
localVue,
methods: {
requestAxios,
},
})
wrapper.setData({
total: '0',
})
wrapper.vm.updateTotalFinancial()
first expect success second not, not update data/variabel total
expect(update).toBeCalled()
expect(wrapper.vm.total).toEqual(100)
Related
My interceptor intercepts a GET request and adds a header to the response based on some conditions.
My Controller
#UseInterceptors(ServiceHeaderInterceptor)
#Get('users')
public async users(
#Query('id') Id: number,
#Query('name') Name: string,
){
const setFlags: MetaFlags = {setCacheHeader: false, setServiceHeader: false};
const data = await this.service.getUsers(id, name, setFlags);
return data;
}
My interceptor looks like this
#Injectable()
export class HeaderInterceptor implements NestInterceptor {
public intercept(
context: ExecutionContext,
next: CallHandler,
): Observable<any> {
return next.handle().pipe(
map((data: { data: DataType, header: 'cache' | 'database' }) => {
const req = context.switchToHttp().getResponse();
if (data.header === 'database') {
res.setHeader('x-api-key', 'pretty secure');
} else {
res.setHeader(xyz, value);
}
return data.data;
}),
);
}
}
This is my test class
const users = [
{
'id': 1,
'name': 'Adam',
},
{
'id': 2,
'name': 'Evan',
},
]
const executionContext: any = {
switchToHttp: jest.fn().mockReturnThis(),
getResponse: jest.fn().mockReturnThis(),
setHeader: jest.fn().mockReturnThis(),
};
const next = {
handle: () => of(users),
};
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
{
provide: UserService,
useValue: mock<UserService>(),
},
ServiceHeaderInterceptor,
],
}).compile();
interceptor = module.get(ServiceHeaderInterceptor);
});
it('get users',async () => {
interceptor.intercept(executionContext, next).subscribe({
next: (value) => {
expect(value).toEqual(users);
},
error: (error) => {
throw error;
},
});
});
});
Is there a way to check what my header values are at this point?
I am able to access only the response body and not the headers.
I need to verify if the header I set in the interceptor is available and has the correct value
I have the below method in my NestJS project:
getAccessToken(): Observable < string > {
return this.httpService.post(`${url}/oauth2/token`, params).pipe(
retryWhen((errors) =>
errors.pipe(
delay(1000),
take(5),
(e) =>
concat(
e,
throwError(
`Error retrieving access token. Tried 5 times.`
)
)
)
),
catchError((err) => {
this.loggerService.error(err);
throw err;
}),
map((res) => res.data),
map((data) => data.access_token)
);
}
The above code will call the API. If successful, it will return access_token, if fails it tries up to 5 times, and if not successful after 5 times, it will throw an exception.
Now I want to write 3 unit tests,
Success when the API is not throwing error and return an access token
Fails 6 times
Fails 2 times and return access token
Test 1:
it('should return access_token', async () => {
const response: AxiosResponse = {
data: {
access_token: 'token1'
},
status: 200,
statusText: 'OK',
headers: {},
config: {}
};
const post = jest
.spyOn(httpService, 'post')
.mockImplementationOnce(() => of(response));
try {
const token = await service.getAccessToken().toPromise();
expect(token).toBe('token1');
} catch (err) {
expect(true).toBeFalsy();
}
});
Test 2:
it('should retry and fails', async () => {
const err: AxiosError = {
config: {},
code: '500',
name: '',
message: '',
response: {
data: {},
status: 500,
statusText: '',
headers: {},
config: {}
},
isAxiosError: true,
toJSON: () => null
};
const post = jest
.spyOn(httpService, 'post')
.mockImplementationOnce(() => throwError(err));
try {
await service.getAccessToken().toPromise();
expect(true).toBeFalsy();
} catch (err) {
expect(err).toBe(
'Error retrieving access token. Tried 5 times.'
);
}
});
However, I can't figure out how to write the test for the 3rd.
I found the solution in case someone else has same problem
it('should retry and return access token', async () => {
const response: AxiosResponse = {
data: {
access_token: 'token1'
},
status: 200,
statusText: 'OK',
headers: {},
config: {}
};
const err: AxiosError = {
config: {},
code: '500',
name: '',
message: '',
response: {
data: {},
status: 500,
statusText: '',
headers: {},
config: {}
},
isAxiosError: true,
toJSON: () => null
};
let retried = 0;
const post = jest
.spyOn(httpService, 'post')
.mockImplementationOnce(() => {
return new Observable((s) => {
if (retried <= 1) {
retried += 1;
s.error(err);
} else {
s.next(response);
s.complete()
}
});
});
try {
const token = await service.getAccessToken().toPromise();
expect(token).toBe('token1');
} catch (err) {
expect(true).toBeFalsy();
}
expect(post).toHaveBeenCalled();
expect(post).toHaveBeenCalledTimes(1);
});
I'm trying to mock a call to AWS.DynamoDB.DocumentClient. I tried several solutions I found online, but I cannot get it to work.
This is my best effort so far:
import * as AWS from 'aws-sdk';
import * as dynamoDbUtils from '../../src/utils/dynamo-db.utils';
jest.mock("aws-sdk");
describe('dynamo-db.utils', () => {
describe('updateEntity', () => {
it('Should return', async () => {
AWS.DynamoDB.DocumentClient.prototype.update.mockImplementation((_, cb) => {
cb(null, user);
});
await dynamoDbUtils.updateEntity('tableName', 'id', 2000);
});
});
});
I get error message
Property 'mockImplementation' does not exist on type '(params: UpdateItemInput, callback?: (err: AWSError, data: UpdateItemOutput) => void) => Request<UpdateItemOutput, AWSError>'.ts(2339)
My source file:
import AWS from 'aws-sdk';
let db: AWS.DynamoDB.DocumentClient;
export function init() {
db = new AWS.DynamoDB.DocumentClient({
region: ('region')
});
}
export async function updateEntity(tableName: string, id: string, totalNumberOfCharacters: number): Promise<AWS.DynamoDB.UpdateItemOutput> {
try {
const params = {
TableName: tableName,
Key: { 'id': id },
UpdateExpression: 'set totalNumberOfCharacters = :totalNumberOfCharacters',
ExpressionAttributeValues: {
':totalNumberOfCharacters': totalNumberOfCharacters
},
ReturnValues: 'UPDATED_NEW'
};
const updatedItem = await db.update(params).promise();
return updatedItem;
} catch (err) {
throw err;
}
}
Please advise how can I properly mock the response of AWS.DynamoDB.DocumentClient.update
Have some way to do the that thing (I think so).
This is one of them:
You use AWS.DynamoDB.DocumentClient, then we will mock AWS object to return an object with DocumentClient is mocked object.
jest.mock("aws-sdk", () => {
return {
DynamoDB: {
DocumentClient: jest.fn(),
},
};
});
Now, AWS.DynamoDB.DocumentClient is mocked obj. Usage of update function like update(params).promise() => Call with params, returns an "object" with promise is a function, promise() returns a Promise. Do step by step.
updateMocked = jest.fn();
updatePromiseMocked = jest.fn();
updateMocked.mockReturnValue({
promise: updatePromiseMocked,
});
mocked(AWS.DynamoDB.DocumentClient).mockImplementation(() => {
return { update: updateMocked } as unknown as AWS.DynamoDB.DocumentClient;
});
mocked import from ts-jest/utils, updateMocked to check the update will be call or not, updatePromiseMocked to control result of update function (success/ throw error).
Complete example:
import * as AWS from 'aws-sdk';
import * as dynamoDbUtils from './index';
import { mocked } from 'ts-jest/utils'
jest.mock("aws-sdk", () => {
return {
DynamoDB: {
DocumentClient: jest.fn(),
},
};
});
describe('dynamo-db.utils', () => {
describe('updateEntity', () => {
let updateMocked: jest.Mock;
let updatePromiseMocked: jest.Mock;
beforeEach(() => {
updateMocked = jest.fn();
updatePromiseMocked = jest.fn();
updateMocked.mockReturnValue({
promise: updatePromiseMocked,
});
mocked(AWS.DynamoDB.DocumentClient).mockImplementation(() => {
return { update: updateMocked } as unknown as AWS.DynamoDB.DocumentClient;
});
dynamoDbUtils.init();
});
it('Should request to Dynamodb with correct param and forward result from Dynamodb', async () => {
const totalNumberOfCharacters = 2000;
const id = 'id';
const tableName = 'tableName';
const updatedItem = {};
const params = {
TableName: tableName,
Key: { 'id': id },
UpdateExpression: 'set totalNumberOfCharacters = :totalNumberOfCharacters',
ExpressionAttributeValues: {
':totalNumberOfCharacters': totalNumberOfCharacters
},
ReturnValues: 'UPDATED_NEW'
};
updatePromiseMocked.mockResolvedValue(updatedItem);
const result = await dynamoDbUtils.updateEntity(tableName, id, totalNumberOfCharacters);
expect(result).toEqual(updatedItem);
expect(updateMocked).toHaveBeenCalledWith(params);
});
});
});
I am trying to create async tests with axios-mock and jest.
This is my test file:
var axios = require('axios');
var MockAdapter = require('axios-mock-adapter');
const middlewares = [thunk,axiosMiddleware]
const mockStore = configureMockStore(middlewares)
describe('async-actions', () => {
var instance;
var mock;
beforeEach(function() {
instance = axios.create();
mock = new MockAdapter(instance);
});
afterEach(() => {
mock.reset()
mock.restore()
})
it('creates FETCH_BOOKINGS_SUCCESS when fetch bookings has been done', () => {
mock
.onGet('/bookings').reply(200, {
data: [
{ id: 1, name: 'test booking' }
]
});
const expectedActions = [
{type: "FETCH_BOOKINGS_START" },
{type: "FETCH_BOOKINGS_SUCCESS", }
]
const store = mockStore({
session: {
token: {
token: "test_token"
}
}
})
return store.dispatch(actions.fetchBookingsTest())
.then(
() => {
expect(store.getActions()).toEqual(expectedActions)
})
// return of async actions
})
})
And my action:
export function fetchBookingsTest() {
return (dispatch) => {
dispatch(async.fetchDataStart(namedType));
return dispatch(rest.get(BOOKINGS))
.then(
(data) => {
dispatch(async.fetchDataSuccess(data,namedType));
},
(error) => {
dispatch(async.fetchDataFailure(error,namedType));
}
)
}
}
I have middleware setup that uses the authentication token from the redux store for each get request. That is why I have setup "test_token" in the mock store.
When I run this test I receive the response
[{"type": "FETCH_BOOKINGS_START"}, {"payload": [Error: Network Error], "type": "FETCH_BOOKINGS_FAILURE"}]
Why am I getting a network error? Do i need to do more setup with Jest to avoid authentication with mock-axios?
I'm having a hard time trying to test an async function that that dispatches another async function:
export function validateVerifyCode(payload, pin) {
return dispatch => {
dispatch(requesting());
return fetch(`${BASE_URL}/register`).then(resp => {
return resp.json()
})
.then(json => {
dispatch(hasSubscriptionCheck(json));
}
})
.catch(error => dispatch(hasError(error)))
}
}
function hasSubscriptionCheck(payload) {
return dispatch => {
dispatch(requesting());
return fetch(`${BASE_URL}/subscriptions`)
.then(resp => resp.json())
.then(json => {
if (json.length == 0) {
dispatch(handleStripeSubmit(payload));
}
})
.catch(error => dispatch(hasError(error)));
}
}
The problem is in my unit test it doesn't actually call hasSubscriptionCheck:
it('validates the verify code', (done) => {
const stub = sinon.stub(Stripe.card, 'createToken');
stub.onCall(0).returns(new Promise((resolve) => {
resolve({});
}));
nock(BASE_URL)
.defaultReplyHeaders({
'Content-Type': 'application/json',
'Authentication': token
})
.post('/register')
.reply(200, {id: 'userid1234'})
.get('/^subscriptions')
.reply(200, []);
const store = mockStore({});
const payload = {
...
};
store.dispatch(actions.validateVerifyCode(payload, '123456'))
.then(() => {
console.log(store.getActions());
})
.then(done)
.catch(done);
})
What's weird though is that when i console.log store.getActions(), I see 2 actions:
[ { type: 'REQUESTING' }, { type: 'REQUESTING' } ]
How I tell the test framework to invoke the second fetch?