How would I mock out the database in my node.js application, which in this case uses mongodb as the backend for a blog REST API ?
Sure, I could set the database to a specific testing -database, but I would still save data and not test my code only, but also the database, so I am actually not doing unit testing but integration testing.
So what should one do? Create database wrappers as a middle layer between application and db and replace the DAL when in testing?
// app.js
var express = require('express');
app = express(),
mongo = require('mongoskin'),
db = mongo.db('localhost:27017/test?auto_reconnect');
app.get('/posts/:slug', function(req, res){
db.collection('posts').findOne({slug: req.params.slug}, function (err, post) {
res.send(JSON.stringify(post), 200);
});
});
app.listen(3000);
// test.js
r = require('requestah')(3000);
describe("Does some testing", function() {
it("Fetches a blogpost by slug", function(done) {
r.get("/posts/aslug", function(res) {
expect(res.statusCode).to.equal(200);
expect(JSON.parse(res.body)["title"]).to.not.equal(null);
return done();
});
});
));
I don't think database related code can be properly tested without testing it with the database software. That's because the code you're testing is not just javascript but also the database query string. Even though in your case the queries look simple you can't rely on it being that way forever.
So any database emulation layer will necessarily implement the entire database (minus disk storage perhaps). By then you end up doing integration testing with the database emulator even though you call it unit testing. Another downside is that the database emulator may end up having a different set of bugs compared to the database and you may end up having to code for both the database emulator and the database (kind of like the situation with IE vs Firefox vs Chrome etc.).
Therefore, in my opinion, the only way to correctly test your code is to interface it with the real database.
There is a general rule of thumb when it comes to mocking which is
Don't mock anything you don't own.
If you want to mock out the database hide it behind an abstracted service layer and mock that layer. Then make sure you integration test the actual service layer.
Personally I've gone away from using mocks for testing and use them for top-to-bottom design helping me drive development from the top towards the bottom mocking out service layers as I go and then eventually implementing those layers and writing integration tests. Used as a test tool they tend to make your test very brittle and in the worst case leads to a divergence between actual behavior and mocked behavior.
I don't agree with the selected answer or other replies so far.
Wouldn't it be awesome if you could catch errors spawned by the chaotic and many times messy changes made to DB schemas and your code BEFORE it gets to QA? I bet the majority would shout heck yes!
You most certainly can and should isolate and test you DB schemas. And you don't do it based on an emulator or heavy image or recreation of you DB and machine. This is what stuff like SQLite is for just as one example. You mock it based on an in memory lightweight instance running and with static data that does not change in that in memory instance which means you are truly testing your DB in isolation and you can trust your tests as well. And obviously it's fast because it's in memory, a skeleton, and is scrapped at the end of a test run.
So yes you should and you should test the SCHEMA that is exported into a very lightweight in memory instance of whatever DB engine/runtime you are using, and that along with adding a very small amount of static data becomes your isolated mocked DB.
You export your real schemas from your real DB periodically (in an automated fashion) and import/update those into your light in memory DB instance before every push to QA and you will know instantly if any latest DB changes done by your DB admins or other developers who have changed the schema lately have broken any tests .
As for the person who replied with the "don't mock anything you don't own". I think he meant to say "don't test anything you don't own". But you DO mock things you do not own! Because those are the things not under test that need to be isolated!
This is what many test driven teams do all the time. You just have to understand the how.
My preferred approach to unit test DB code in any language is to access Mongo through a Repository abstraction (there's an example here http://iainjmitchell.com/blog/?p=884). Implementations will vary in terms of DB specific functionality exposed but by removing all the Mongo code from your own logic you're in a position to Unit Test. Simply replace the Mongo Repository implementation with a stubbed out version which is trivially easy. For instance, just store objects in a simple in-memory dictionary collection.
You'll get the benefits of unit testing your own code this way without DB dependencies but you'll still need to do integration tests against the main DB because you'll probably never be able to emulate the idiosyncrasies of the real database as others have said here. The kind of things I've found are as simple as indexing in safe mode vs without safe mode. Specifically, if you have a unique index your dummy memory implementation might honour that in all cases, but Mongo won't without safe-mode.
So whilst you'll still need to test against the DB for some operations, you'll certainly be able to unit test your own logic properly with a stubbed out Repository implementation.
The purpose of mocking is to skip the complexity and unit test own code. If you want to write e2e tests then use the db.
Writing code to setup/teardown a testing DB for unit testing is technical debt and incredibly unsatisfying.
There are mock libraries in npm:
mongo - https://www.npmjs.com/package/mongomock
mongoose - https://www.npmjs.com/package/mockgoose
If those don't support the features you need, then yes you may need to use the real thing.
I had this dilemma and chosen to work with a test DB and clean it every time the test begins. (how to drop everything: https://stackoverflow.com/a/25639377/378594)
With NPM you can even make a test script that creates the db file and cleans it up after.
Related
I'm using nodejs to create an end to end test suite for our API. Before each test runs, I need to insert database records for that test. Many of the tables in question do not use native auto-increment type fields for their primary keys.
(I know, bad database design. But I don't have control over that.)
Instead, I have a Postgres database server to connect.
As I begin to set up my tests, I am finding that my transactions are colliding with each other because of the asynchronous nature of javascript. Basically, the transactions are getting the same sequence numbers and then trying to commit on top of each other. So unique constraints are failing.
The first solution that comes to my mind (I'm open to others) is to just set up all of the database records before any tests run. But to my knowledge, Jasmine's beforeAll() function only applies to the file that it's in. I need a beforeAll() function that runs before all Jasmine tests run in all files everywhere.
Does Jasmine have something like that? If not, is there a way I can create a controller in nodejs that will set up the test cases in the database and then spawn jasmine programmatically?
Thanks in advance!
We've got an application in Django running against a PGSQL database. One of the functions we've grown to support is real-time messaging to our UI when data is updated in the backend DB.
So... for example we show the contents of a customer table in our UI, as records are added/removed/updated from the backend customer DB table we echo those updates to our UI in real-time via some redis/socket.io/node.js magic.
Currently we've rolled our own solution for this entire thing using overloaded save() methods on the Django table models. That actually works pretty well for our current functions but as tables continue to grow into GB's of data, it is starting to slow down on some larger tables as our engine digs through the current 'subscribed' UI's and messages out appropriately which updates are needed as which clients.
Curious what other options might exist here. I believe MongoDB and other no-sql type engines support some constructs like this out of the box but I'm not finding an exact hit when Googling for better solutions.
Currently we've rolled our own solution for this entire thing using
overloaded save() methods on the Django table models.
Instead of working on the app level you might want to work on the lower, database level.
Add a PostgreSQL trigger after row insertion, and use pg_notify to notify external apps of the change.
Then in NodeJS:
var PGPubsub = require('pg-pubsub');
var pubsubInstance = new PGPubsub('postgres://username#localhost/tablename');
pubsubInstance.addChannel('channelName', function (channelPayload) {
// Handle the notification and its payload
// If the payload was JSON it has already been parsed for you
});
See that and that.
And you will be able to to the same in Python https://pypi.python.org/pypi/pgpubsub/0.0.2.
Finally, you might want to use data-partitioning in PostgreSQL. Long story short, PostgreSQL has already everything you need :)
I'm developing APIs for social networking web application for learning perspective. When I started to write test cases I stuck around how to organize/write test cases.I'm initially proceeding like this:
First setup global data base initialization:
I need some users' auth tokens to test my routes so I decide to set up these information at global context. Also there are other information that also need to setup at global context so I'm setting that too.
Then for each route:
I start to write test cases and thought that I would write test cases in
such a way that each route test cases would be independent to each other.
and after completing all test suites:
I thought that I would clean up my data base.
The problems with this approach I'm facing are:
Say I want to test four routes named /users , /users/:id/my_invites , /send_invites, /response_invites. And further suppose I'm only interested in writing test cases for GET request and response for /users , /users/:id/invites and POSTing data in the case of others.
/send_invites, /response_invites definitely trigger some actions on the server side that modifies the data base state.
As we see that these routes effect the state of other routes' data say one user sends invites to another user and gets response true/false, so for that user his request was successful but how to ensure that another user actually received the invitation if we don't checking his received invitation documents(i.e through another route) in the first route test cases. Means /send_invites effects the /users/:id/my_invites .
because these routes are dependent on each others
So The questions I want to ask are:
how to write test cases for these routes so that each route would be independent ?
I tried with three dummy testing users in the global context and trying all sort of combinations for them in all test suites.My test suit presently deals with more than one routes to check 1 route true functionality.
Can anyone suggest me better solution for writing test cases for the above mentioned scenarios?
May be my question is too long or not clear. Please let me know and help me if you can.
My opinion:
First the bases EACH test case should have a fresh new state. That means that before you check one scenario, you want to flush your database and insert your new data prepared to test that case scenario. You can use a real database o mock one with data in-memory or however you prefer.
Second, each endpoint potentially affects a lot of tables in your database. So it's perfectly normal to check the state of your data, independently of the tables to check that the information is correct.
And well mocha and other test frameworks have functions that help you to do that. Like beforeEach and afterEach to set up and tear down your data before each test case.
Hi I´m trying to make a unit test creating some fake data and executing a request (using supertest) to check if the controller works well.
The problem rise up when the controller tries to get the fake data, because it exists only inside the transaction.
So my questions are:
Did someone make a junit like test using node.js and express?
How do you manage the database data? How do you do rollback on it?
Thanks in advance.
If I'm understanding you correctly, you are trying to run a bunch of api calls with some fake data, but you are unable to actually get the data from database?
If that's the case, one of two things I would suggest:
Allow your api to update the db, then retrieve from db. When your tests are done, you can do the full clean up at that point (that can be achieve via the after() in mocha)
Use sinon.js, and stub all db calls to return some fake data that you know.
I am using LocomotiveJS to build an MVC application. I have been thinking about the type of tests I should write and am confused.
Here are the different components in the application - Models, Views, Controllers, Router and the ORM.
If I had to unit test every component, here is how I think I should approach it.
Write tests to ensure the API provided by ORM act the way I expect it to.
Unit test my Model stubbing the ORM. I provide it the stub so I do not have to rely on actual database operations in my unit test.
A Controller accesses Views and Models. A Controller's job is to get/modify the model and to respond to the client (render/redirect).
The controller's response can be tested by providing them test inputs and checking if the right response is generated (stub out render/redirect and make sure the right calls are made).
Model manipulation by the controller can be tested by stubbing out the model and ensuring the right calls are made. This feels wrong, since I am testing the implementation...
Views are just templates; the controller binds the templates with values. I could create a fake view model and bind it to the view and see if the right output is generated.
Routes just take the request and map it to the right Controller and Action. I can ensure the right routes are supported by the app by stubbing out parts of the Router and making sure a request to the router is mapped to the expected Controller/Action.
Say I change a model API now, I have to change the model test, I have to change the model stubs used by the controller test and I have to update the assertions in controller test.
This seems like overkill.
Does this rather make sense?
Do 1 and 2 as above.
3. Integration test the rest (Controller/View/Router). Here I think I should just start up my app in a test environment and use supertest to ensure the requests generate the right responses - visiting an url, I get the right content, right redirects etc.
I think it makes sense to unit test the model because it represents an interaction with a different system (data persistence). We want to make sure the bridge functions properly. Router/Controller/View interact within our own system and in very specific ways. So it seems okay to integration test that. What are your thoughts?
If you rely on integration tests, you will lose the benefits of unit tests. Your tests will run more slowly than they need to and will therefore be run less often. Your tests will not tell you where you broke something. Your tests will not exercise as much of the functionality of the application. Your tests will be only half as effective as documentation. You will not be able to TDD.
Overall, any time someone chooses to forgo unit tests in the interest of speed, they go more slowly.