With React Native, NodeJS + KoaJS and MongoDB set up, we can start connecting them with each other.

KoaJS ↔ MongoDB

As I want to learn and practice Test-Driven Development, we'll be creating tests first and it seems that Mocha is recommended over Jest to test Mongoose (which we'll be using later). We'll also be using supertest for integration testing.

yarn add mocha --dev yarn add supertest --dev

Create a test file like this:

```javascript // server.test.js const request = require('supertest'); const app = require('./koa');

describe('Server', () => { it('is running', done => { request(app) .get('/') .expect(200, done); }); }); ```

and change package.json as following: javascript // package.json ... "scripts": { ... "test": "mocha server.test.js --watch", ... }, ...

I've used mocha './server/*.test.js' --recursive --watch instead so it runs all test files inside server folder. We'll probably change this later.

Run yarn test and find that TypeError: app.address is not a function because app doesn't exist yet thus it's time to write the actual code

```javascript // server.js const Koa = require('koa');

const app = new Koa();

app.use(async ctx => { ctx.body = "Hello World, I'm Koa"; });

module.exports = app.listen(3000, () => console.log('Running on http://localhost:3000/'), ); `` Don't forget tomodule.exportsit. Now our first test is passing, but it can throwUncaught Error: listen EADDRINUSE: address already in use :::3000when trying to run the test again or **--watch**ing it. We have to [close](https://github.com/visionmedia/supertest/issues/437) the server after each test, so add this insidedescribe()` block

javascript // server.test.js ... afterEach(() => { app.close(); }); ...

With Koa working and being tested, we can now try to read some information from our MongoDB instance.

Let's try to find our stampler by adding this test javascript // server.test.js ... it('finds our stampler', done => { request(app) .get('/') .expect(/Stampler/) .expect(200, done); });

It'll return Error: expected body 'Hello World, I\'m Koa' to match /stampler/ because ctx.body is a plain text, not the data in our database. To access it, we'll use Mongoose yarn add mongoose or npm install mongoose

Create a Product.js to define a new schema ```javascript // Product.js var mongoose = require('mongoose');

const ProductSchema = mongoose.Schema({ title: String, });

module.exports = mongoose.model('Product', ProductSchema); ```

And use it as it follows ```javascript // server.js const Koa = require('koa'); const mongoose = require('mongoose'); const Product = require('./Product');

const app = new Koa();

mongoose.connect('mongodb://127.0.0.1:27017/test', {useNewUrlParser: true});

app.use(async ctx => { //ctx.body = "Hello World, I'm Koa"; ctx.body = await Product.find({}); });

module.exports = app.listen(3000, () => console.log('Running on http://localhost:3000/'), );

```

Note that your MongoDB should be running or you'll get MongoNetworkError: failed to connect to server [127.0.0.1:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017] You can check it by running mongo in the terminal and sudo services mongodb start to start it.

It should work at first, however you might notice an error if --watching the test suite: OverwriteModelError: Cannot overwrite 'Product' model once compiled. To fix it, add this beforeEach like you did with afterEach, so it deletes the Product model before testing again. javascript // server.test.js ... beforeEach(async () => { const url = 'mongodb://127.0.0.1:27017/test'; await mongoose.connect(url, {useNewUrlParser: true}); delete mongoose.connection.models.Product; }); ...

While we're on it, let's try to add a new product, check if it exists and clean it after. Let's also separate some describes ```javascript // server.test.js const request = require('supertest'); const mongoose = require('mongoose'); const app = require('./app'); const Product = require('./Product');

describe('Server', () => { describe('without acessing MongoDB', () => { afterEach(() => { app.close(); });

it('is successful', done => {
  request(app)
    .get('/')
    .expect(200, done);
});

it('finds our stampler', done => {
  request(app)
    .get('/')
    .expect(/Stampler/)
    .expect(200, done);
});

});

describe('acessing MongoDB direcly', () => { afterEach(() => { Product.deleteOne({title: 'skate'}).exec(); });

beforeEach(async () => {
  const url = 'mongodb://127.0.0.1:27017/test';
  await mongoose.connect(url, {useNewUrlParser: true});
  delete mongoose.connection.models.Product;
});

it('creates and finds a skate', done => {
  const skate = new Product({title: 'skate'});
  skate.save();
  request(app)
    .get('/')
    .expect('Content-Type', /json/)
    .expect(/skate/)
    .expect(200, done);
});

}); });

```

This probably isn't the optimal and most elegant way to test integration, but I'll leave the comments open for hints and suggestions

References

Hackernoon - API testing using SuperTest Bits and Pieces- Build a Unit-Testing Suite with Mocha and Mongoose Zellwk - Connecting Jest and Mongoose SmoothTerminal - Build an API with Koa.js