How to reset dynamodb local data for unit testing - jestjs

using Jest, DynamoDB Local, I wanna reset database for each test so it doesn't have to be in specific order.
Is there any way to do that wisely?
beforeEach(() => {
resetDB()
})
it('create a data', () => {
})
it('remove the data', () => {
})
it('find the data', () => {
test should pass but it fails because the data is removed.
})

I would look into #shelf/jest-dynamodb to get started.
I wrote a testing library for AWS services, but it uses the real DyanmoDB and not the local version.
You could try using the code here to delete all items from a table.

Related

Testing Angular Services with MSW causes timeout

EDIT: I should mention, that I only have problems during testing. When I run ng serve and use msw to serve the data everything works correctly.
I stumbled upon mswjs recently and wanted to use the mock service workers to test my frontend services without waiting on the backend team and avoid having to write mock-service classes. I setup everything according to the examples provided in the documentation.
At first I got the message that stating spec 'UserService should get list of users' has no expectations.
I researched this and added a done() function call at the end of my subscribe callback. After doing that, I get the following error:
Error: Timeout - Async function did not complete within 3000ms (set by jasmine.DEFAULT_TIMEOUT_INTERVAL) in node_modules/jasmine-core/lib/jasmine-core/jasmine.js (line 7609)
I already tried increasing the default_timout in Karma but even setting it to 30.000 did not change the result.
I also tried working around by using waitForAsync without any success. This way I get no error and the test succeeds but only because it still finds no expectations within the spec.
Most example I found online do not deal with mock service workers and instead resort to using mock-services and fakeasync which does not help in my case.
This is how my code looks like:
My Angular Service:
#Injectable({
providedIn: 'root'
})
export class UserService {
private url = 'http://localhost:3000/api/users';
constructor(private http: HttpClient) { }
getUser(id: string): Observable<User> {
return this.http.get<User>(`${this.url}/${id}`);
}
listUsers(): Observable<User[]> {
return this.http.get<User[]>(this.url);
}
}
My Test Code:
describe('UserService', () => {
let service: UserService;
beforeAll(() => {
worker.start();
});
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientModule],
});
service = TestBed.inject(UserService);
});
afterAll(() => {
worker.stop();
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should get list of users', (done) => {
service.listUsers().subscribe((data) => {
expect(data.length).toBe(5);
done();
});
})
});
The Worker setup:
const handlers = [
rest.get('http://localhost:3000/api/users', (req, res, ctx) => {
return res(
ctx.status(200),
ctx.json(users))
})
]
export const worker = setupWorker(...handlers)
I managed to solve my own problem by using firstValueFrom and waitForAsync.
I changed the code in my tests to the following:
it('should get list of users', waitForAsync(async () => {
const source$ = service.listUsers();
const result = await firstValueFrom(source$);
expect(result.length).toEqual(5);
}));

Firebase-admin nodejs SDK doens't connect

I'm attempt to connect to firebase/firestone using the nodejs SDK,however I it doesn't connect. I've attempted to connect multiple times, using setInterval but nothing works.
First, I initialize the the firebase using the credentials and the databaseURL, after this I get the databaseRef, and in the end I attempt to write to the database.
I've checked the ./info/connected on setInterval with timeout of 1000ms and mocha --timeout flag to 5000ms, and always marks as offline.
I've checked the credentials, when is a wrong credential or config json, they give an JSON parse error message(cause I have several storage instances, each connected according to a flag spawned during the execution time).
I'm using the TDD approach on my application, so, I have to mock the entire database and check against the resulted values of each operation. I've wrote a controller for the task of handling the firebase/firestone work, but I if I can't connected it has no use.
The code goes here:
const analyticsFirebaseMock = admin.initializeApp({
credentials: admin.credential.cert(analyticsCredentials),
databaseURL: process.env.ANALYTICS_FIREBASE_URL
}, 'analyticsMock')
const analyticsDbRef = analyticsFirebaseMock.database()
beforeEach(() => {})
afterEach(() => sinon.restore())
describe('POST - /analytics', () => {
it('should save the analytics data for new year', async (done) => {
const itens = 1
const price = 599.00
setInterval(() => {
clockAnalyticsDbRef.ref(`.info/connected`).once('value', (value) => {
if (value.val() === true) console.log('connected')
else console.error('offline')
})
}, 1000)
await analytics.updateAnalytics(user, itens, price)
await analyticsDbRef.ref(`${user}`).once('value', (value) => {
expect(R.view(userLens, value)).to.be.equals(user)
done()
})
})
})
In the above code, I use async/await on analyticsDbRef cause of the asynchronous characteristic of the js. Call the controller, await the query result, conclude with done. The test fails with timeout, expecting done to be called.
What could I doing wrong?

Node JS GET API's not working with new data

I am using Node JS and MYSQL. When I add new data to my project, it writes to the database. Then when I want to GET this data with another API, it doesn't come. When I try again after about a minute, it comes on. However, right after I send a request via Swagger, data comes from the outside (Postman or Panel) on my request again.
My simple Controller.
exports.GetAll = (req, res, next) => {
ThisModel.GetAllSQL()
.then((response) => {
res.status(200).json(response[0]);
}).catch((error) => {
res.status(400).send();
console.log('Senaryo listesi çekilirken bir hata meydana geldi: ' + error);
})
}
.then((response) => {
res.status(200).json(response[0]);
})
Judging from the line above, it looks like you're getting a list/array of data, but only returning the first item in the list response[0].
Maybe this is what you're looking for:
.then((response) => {
res.status(200).json(response);
})

Running multiple mocha files and suites with same context

I'm trying to run several integration tests with some shared context. The context being shared is a single express application, and I'm trying to share it across suites / files because it takes a few seconds to spin up.
I got it to work by instantiating a "runner" mocha test suite, that would have test functions that would just require each test file as needed, and this was working well (a side effect is that the test requiring the child test file would finish as "success" before any of the tests inside the file would actually run, but this was a minor issue)
// test-runner.js:
describe('Integration tests', function () {
let app
let log
this.timeout(300000) // 5 mins
before(function (done) {
app = require('../app')
app.initialize()
.then(() => {
done()
})
.catch(err => {
log.error(err)
done(err)
})
})
it('Running api tests...', (done) => {
require('./integration/api.test')(app)
done()
})
// ./integration/api.test.js:
module.exports = (app) => {
let api = supertest.agent(app)
.set('Content-Type', 'application/json')
describe('Authorization', () => {
describe('Trying to access authorization sections', () => {
it('should be denied for /home', async () => {
await api.get(`${baseUrl}/home`)
.expect(STATUS_CODE.UNAUTHORIZED)
})
...
The Problem:
I want to signal the test runner that all of the tests in the imported suite have finished, so I can call shutdown logic in the test runner and end the test cleanly. In standard test functions, you can pass a done function to signal that the code in the test is complete, so I wrapped each of the child tests in a describe block to use the after hook to signal that the whole test module was done:
// test-runner.js:
describe('Integration tests', function () {
let app
let log
this.timeout(300000) // 5 mins
before(function (done) {
app = require('../app')
app.initialize()
.then(() => {
done()
})
.catch(err => {
log.error(err)
done(err)
})
})
it('Running api tests...', (done) => {
require('./integration/api.test')(app, done)
})
// ./integration/api.test.js:
module.exports = (app, done) => {
let api = supertest.agent(app)
.set('Content-Type', 'application/json')
describe('All api tests', () => {
let api
before(() => {
api = supertest.agent(app)
.set('Content-Type', 'application/json')
})
after(() => {
done() // should be calling the done function passed in by test runner
})
describe('Authorization', () => {
describe('Trying to access authorization sections', () => {
it('should be denied for /home', async () => {
await api.get(`${baseUrl}/home`)
.expect(STATUS_CODE.UNAUTHORIZED)
})
...
but when I do this, the test suites just don't run. The default timeout will just expire, and if I set a higher timeout, it just sits there (waiting for the longer timeout). If I hook into a debug session, then the test exits immediately, and the after hook (and before!) never get called.
I'm open to other ideas on how to do this as well, but I haven't found any good solutions that that allow sharing some context between tests, while having them broken into different files.

reset a database before each test

I'm using node and supertest for a simple app. I got SQlite3 for the local test database. I did a simple test to get a super inserted into the database. I wanted to reset the database each time a test is run. I'm looking in the docs right now and can't seem to locate it. I figured I would ask here because it seems someone would most likely know the info.
const request = require('supertest');
const server = require('../server');
describe('Authentication', function() {
//database reset here
it('should create a new user /users/registration', function(done) {
request(server)
.post('/users/register')
.send({
username: 'user-name',
email: 'luser-name#gmail.com',
password: '12345'
})
.set('Accept', 'application/json')
.expect(201, done);
});
});
If you want to run any piece of code before each test, you can use beforeEach function in jest
describe('my test', () => {
beforeEach(() => {
// code to run before each test
});
test('test 1', () => {
// code
});
test('test 2', () => {
// code
});
});
So best way to do this is have some logic in your routing functions of your Api
Receive an API request
Check if ['X-MOCK-HEADER'] exists
If it does then route to the mock version of the endpoint
So your mock for create user would always return 201 OK - your mock endpoint would do something like this:
const routes = {
CREATE_USER_OK:() => { return {....} } // make sure these return proper http responses
CREATE_USER_BAD_REQUEST: () { return {...} }
}
return routes[HEADER_VALUE]()
The reason being you're testing the route not the database class in this instance, so you just want to return static data, if you wanna test something else then just change the X-MOCK-HEADER value to whatever you want and add the mock route to return the right http response/code - I'd need to know what the API code looked like to help you on the backend implementation.
If possible stay away from messing with staging databases for testing because down the road you will suffer a LOT of pain as it gradually gets filled with garbage.
Also if you're working with a front end app you can quickly prototype with static data - this is especially useful if you've got a front end team waiting for an API endpoint to say create a login screen.
There's no defined way to reset a sqlite db, just delete the db and recreate.
Sqlite: How do I reset all database tables?
I did this in the file and it works fine
const request = require('supertest');
const server = require('../server');
const knex = require('knex');
const dbConfig = require('../knexfile.js')['test'];
const db = knex(dbConfig);
describe('Authentication', () => {
beforeEach(async () => {
await db('users').truncate();
});
it('should create a new user /users/registration', function(done) {
request(server)
.post('/users/register')
.send({
username: 'user-name',
email: 'luser-name#gmail.com',
password: '12345'
})
.set('Accept', 'application/json')
.expect(201, done);
});
});

Resources