{"id":3400,"date":"2018-03-28T12:59:42","date_gmt":"2018-03-28T10:59:42","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=3400"},"modified":"2023-06-18T18:32:03","modified_gmt":"2023-06-18T16:32:03","slug":"testing-a-mongodb-with-nodejs-mocha-and-mongoose","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/testing-a-mongodb-with-nodejs-mocha-and-mongoose\/","title":{"rendered":"Testing a MongoDB with NodeJS, Mocha and Mongoose"},"content":{"rendered":"<p style=\"text-align: left; margin-bottom: 10px;\"><em>Related articles:&nbsp;\u25ba<a href=\"https:\/\/wp.me\/p71Rzi-Tb\">Take Me Home &#8211; Project Overview<\/a>&nbsp; \u25ba<a href=\"https:\/\/wp.me\/p71Rzi-RU\">CI\/CD infrastructure: Choosing and setting up a server with Jenkins as Docker image&nbsp;<\/a>\u25ba<a href=\"https:\/\/wp.me\/p71Rzi-RH\">Android SDK and emulator in Docker for testing<\/a>&nbsp; \u25ba<a href=\"https:\/\/wp.me\/p71Rzi-SN\">Automated Unit- and GUI-Testing for Android in Jenkins<\/a>&nbsp;<\/em><\/p>\n<hr style=\"padding-top: 1px;\">\n<p><strong>Setting up the testing environment and workflow<\/strong><\/p>\n<p><strong>Setup:<\/strong><\/p>\n<ul>\n<li>Jenkins CI Docker Container<\/li>\n<li>MongoDB Docker Container<\/li>\n<li>Production-MongoDB on mlab.com<\/li>\n<li>NodeJS Web-Application, hosted on heroku.com<\/li>\n<\/ul>\n<p>Regarding our database tests we wanted to achieve two things: first of all, we wanted to test any functions of our web application using mongoose which change persistent data. Secondly, we needed database tests to test if eventual model-changes are compatible with our data in the production database.<br \/>\nIn relational database management systems one defines constraints in the database, which are tested by the database tests. Since we are using MongoDB though, we don\u2019t really have any constraint in the database. Instead we can define any needed constraints with mongoose right in the application. Therefore, cloning the production database for testing is only required when migrating data (or when having constraints defined) but non-essential for the consistency of the as-is backend.<br \/>\nSo alternatively when testing a MongoDB we could also use a shell-script or a \u201cbefore\u201d-function, that gets called once before starting the tests, to define our database testing environment, like creating the same collections we have in the production database and put in test data for our test cases.<br \/>\n<!--more--><br \/>\nSumming up, the workflow is the following:<\/p>\n<ul>\n<li>Start docker container with our test-MongoDB.<\/li>\n<li>Configure testing environment: Either copy collections from production database or set it up with a shell-script\/before-function.<\/li>\n<li>When copying data from the production-database, we need to drop all documents in the collections and then fill it with known test data (\u201cknown-state\u201d \u2013 principle).<\/li>\n<li>The test-database can be filled with testdata via \u201cbefore\u201d-methods using mocha.<\/li>\n<li>Start database test using the configured MongoDB-test-environment.<\/li>\n<li>Collect results and trigger next step of the Jenkins-CI.<\/li>\n<li>Stop docker container with our test-MongoDB.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p><strong>Implementing database-tests with mocha.<\/strong><\/p>\n<p>Using mocha, we can configure test-cases with the \u201cit\u201d-keyword in a \u201cdescribe\u201d-block. Each test-case in a \u201cdescribe\u201d-block will be sequentially called. So even though it would be possible to configure test-cases that build up on each another, like:<\/p>\n<ul>\n<li>First testcase puts in new data<\/li>\n<li>Second testcase modifies the new data<\/li>\n<li>Third testcase deletes the data.<\/li>\n<\/ul>\n<p>it is a \u201cNoNo\u201d. Why? Imagine the first testcase would fail: all following test cases, that built up on the first one would fail too, and we won\u2019t really have a concrete indication where the error originated from. What we want to do instead, is to kind of reset the database before each test case with a \u201cbeforeEach\u201d-function, provided by mocha. It is wise to do this in the \u201cbeforeEach\u201d-function to be sure, that a test is using the defined test-data. If we define it in the \u201cafterEach\u201d-function, we cannot be 100% sure that it is called (in case a test crashes).<br \/>\nIf we keep this pattern, each test can be triggered independently from other test cases, therefore increasing trackability of the error origination.<br \/>\nWe are also using the module \u201cshould\u201d, to easily define expected test results.<br \/>\nThe following demonstrates the implementation, using pseudo-code to some extent:<\/p>\n<pre class=\"prettyprint lang-javascript\" data-start-line=\"1\" data-visibility=\"visible\" data-highlight=\"\" data-caption=\"\">var should = require('should')\n\nconst sampleUser = {\n    username: username,\n    password: password\n}\n\nbefore(\u2018set up test-environment\u2019,function(){\n\/\/connect to test-database\n\/\/create collections\n\/\/done();\n})\n\nbeforeEach('drop and create test data',function(){\n\/\/wipe out all data in collections\n\/\/create test-data entries in collections\n})\n\ndescribe('Model User', function () {\n    it('add user', function (done) {\n        should(sampleUser).have.property('username', username);\n        User.saveUser(sampleUser, (error, user) =&gt; {\n            should.not.exist(error);\n            should.exist(user);\n            should(user).have.property('username', username);\n            should(user).have.property('password', password);\n            done()\n        });\n    });\n    \/*\n    define more testcases\n    *\/\n})<\/pre>\n<p>Imagine we somehow don\u2019t have the possibility (or don\u2019t want) to clone the production database into our test-environment and therefore have to set it up ourselves.<br \/>\nIn the \u201cbefore\u201d-function, that is called once before all our test-cases are started, we connect to our test-database in the docker container and create the collections we are also using in the production database. In the \u201cbeforeEach\u201d-function we first wipe out any existing data (if something is left over from previous tests) from our collections. Then we create new documents in our collections that we eventually need for our test cases.<br \/>\nIn the test case itself, we save the \u201csampleUser\u201d-object to our database and expect in the callback, that we won\u2019t receive an error and that the fields we wanted to set, are set appropriately.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Conclusion<\/strong><\/p>\n<p>When testing your non-relational database like MongoDB there is no perfect way that you can use in ALL of your projects, it will always depend on the current circumstances and needs of the project.<br \/>\nSomething to keep in mind though:<\/p>\n<ul>\n<li>Never (or at least very very rarely) run tests against your production database, it might compromise your live-data.<\/li>\n<li>When working with mongoose, don\u2019t define further constraints in your database. Then you are free to generate collections from your models rather than copying them from the database. Copying is great, but it\u2019s not needed, so always keep in mind what you want to achieve and look for a good balance between cost and reward.<\/li>\n<li>Known-state-principle: Always organize your test-database to a known-state so that you can eliminate unreproducible side-effects.<\/li>\n<\/ul>\n<p>With these guidelines helping you out, you are set to run your own database-tests in your next project.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Related articles:&nbsp;\u25baTake Me Home &#8211; Project Overview&nbsp; \u25baCI\/CD infrastructure: Choosing and setting up a server with Jenkins as Docker image&nbsp;\u25baAndroid SDK and emulator in Docker for testing&nbsp; \u25baAutomated Unit- and GUI-Testing for Android in Jenkins&nbsp; Setting up the testing environment and workflow Setup: Jenkins CI Docker Container MongoDB Docker Container Production-MongoDB on mlab.com NodeJS Web-Application, [&hellip;]<\/p>\n","protected":false},"author":869,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[656,262,651,2],"tags":[157,156,155,158,25],"ppma_author":[743],"class_list":["post-3400","post","type-post","status-publish","format-standard","hentry","category-databases","category-rich-media-systems","category-system-designs","category-system-engineering","tag-database-testing","tag-mocha","tag-mongodb","tag-mongoose","tag-nodejs"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":3421,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/take-me-home-project-overview\/","url_meta":{"origin":3400,"position":0},"title":"Take Me Home &#8211; Project Overview","author":"cp054","date":"28. March 2018","format":false,"excerpt":"Related articles:\u00a0\u25baCI\/CD infrastructure: Choosing and setting up a server with Jenkins as Docker image\u00a0\u25baDockerizing Android SDK and Emulator for testing\u00a0 \u25baAutomated Unit- and GUI-Testing for Android in Jenkins\u00a0 \u25baTesting a MongoDB with NodeJS, Mocha and Mongoose During the winter term 2017\/2018, we created an app called Take Me Home. The\u2026","rel":"","context":"In &quot;Mobile Apps&quot;","block_context":{"text":"Mobile Apps","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/interactive-media\/mobile-apps\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/tmh_admin_usermanagement_bearbeitet.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":3329,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/android-sdk-and-emulator-in-docker-for-testing\/","url_meta":{"origin":3400,"position":1},"title":"Android SDK and emulator in Docker for testing","author":"Michael Laemmle","date":"28. March 2018","format":false,"excerpt":"Related articles:\u00a0\u25baTake Me Home - Project Overview\u00a0 \u25baCI\/CD infrastructure: Choosing and setting up a server with Jenkins as Docker image\u00a0 \u25baAutomated Unit- and GUI-Testing for Android in Jenkins\u00a0 \u25baTesting a MongoDB with NodeJS, Mocha and Mongoose During our Android development project, we had to cope with several technological and organizational\u2026","rel":"","context":"In &quot;Mobile Apps&quot;","block_context":{"text":"Mobile Apps","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/interactive-media\/mobile-apps\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/Pipeline.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/Pipeline.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/Pipeline.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/Pipeline.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/Pipeline.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":3397,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/automated-unit-and-gui-testing-for-android-in-jenkins\/","url_meta":{"origin":3400,"position":2},"title":"Automated Unit- and GUI-Testing for Android in Jenkins","author":"Benedikt Schrade","date":"28. March 2018","format":false,"excerpt":"Related articles:\u00a0\u25baTake Me Home - Project Overview\u00a0 \u25baCI\/CD infrastructure: Choosing and setting up a server with Jenkins as Docker image\u00a0\u25baAndroid SDK and emulator in Docker for testing\u00a0 \u00a0\u25baTesting a MongoDB with NodeJS, Mocha and Mongoose In this article we would like to describe, how to write unit- and gui-tests for\u2026","rel":"","context":"In &quot;Mobile Apps&quot;","block_context":{"text":"Mobile Apps","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/interactive-media\/mobile-apps\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":3342,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/03\/28\/ci-cd-infrastructure-choosing-and-setting-up-a-server-with-jenkins-as-docker-image\/","url_meta":{"origin":3400,"position":3},"title":"CI\/CD infrastructure: Choosing and setting up a server with Jenkins as Docker image","author":"cp054","date":"28. March 2018","format":false,"excerpt":"Related articles:\u00a0\u25baTake Me Home - Project Overview\u00a0 \u25baAndroid SDK and emulator in Docker for testing\u00a0 \u25baAutomated Unit- and GUI-Testing for Android in Jenkins\u00a0 \u25baTesting a MongoDB with NodeJS, Mocha and Mongoose This article will run you through the motivation for a continuous integration and delivery, choosing a corresponding tool and\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/puttygen.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/puttygen.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/puttygen.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/03\/puttygen.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":2859,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2017\/08\/31\/iot-with-the-raspberry-pi-final-application-part-3\/","url_meta":{"origin":3400,"position":4},"title":"IoT with the Raspberry Pi \u2013 Final application \u2013 Part 3","author":"mr143@hdm-stuttgart.de","date":"31. August 2017","format":false,"excerpt":"In our final application, we have put together a solution consisting of four different modules. First, we have again the Raspberry Pi which raises and sends the sensor data using the already presented Python script. We changed the transfer protocol in the final application to MQTT, which gives us more\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/08\/mqtt-1024x465.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/08\/mqtt-1024x465.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/08\/mqtt-1024x465.jpg?resize=525%2C300&ssl=1 1.5x"},"classes":[]},{"id":632,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2016\/07\/26\/test-driven-development-part-iii\/","url_meta":{"origin":3400,"position":5},"title":"Test Driven Development Part III","author":"Matthias Schmidt","date":"26. July 2016","format":false,"excerpt":"[written by Roman Kollatschny and Matthias Schmidt] Uhwe, hello and welcome back to the third of our posts in this series. Today we want to show you additional features and tipps on developing a node.js web application test driven. As stated in the last article we use Mocha.js and Chai.js\u2026","rel":"","context":"In &quot;System Designs&quot;","block_context":{"text":"System Designs","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/system-designs\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":743,"user_id":869,"is_guest":0,"slug":"dj026","display_name":"Domenik Jockers","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/16d1c57c9032ce116ecfa6b985db0ea3442f461f1fb13181481164143fc3675a?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/3400","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/users\/869"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=3400"}],"version-history":[{"count":11,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/3400\/revisions"}],"predecessor-version":[{"id":24746,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/3400\/revisions\/24746"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=3400"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=3400"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=3400"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=3400"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}