I set up a server that provides several endpoints to clients, and I have a client that uses node-rest-client package to post data to the backend.
I would like to write some unit-testing for the client side, making sure the data is properly sent to the endpoint.
I've been thinking of setting a dummy server for the testing, but that doesn't feel right.
How can i acheive such tests?
Please let me know if there's any missing data.
Thanks in advance!
EDIT
I've been looking at supertest package, but it looks like this is used to test the REST API service itself and not to test the REST calls from the client
Setting up a dummmy server is a legitimate approach as part of your "Acceptance Testing" strategy. Unlike Unit Tests, Acceptance Tests test a single component (made up of many Units) in isolation, stubbing out any external factors like databases or back end HTTP services. Having a dummy server can be a good way to go if you want to test how your client side as a whole interacts with the back end HTTP service. Acceptance Tests are generally more wide reaching, fewer in number, and slower than Unit Tests. That's why it's OK to start a dummy HTTP server.
However, if you really want to Unit Test the individual javascript unit that makes calls to the server, then this can actually be a bit tricky. You don't want to start a real HTTP server in Unit Tests because it will make them slow and unable to run in parallel.
The best approach depends on the technology you are using. For example, AngularJS provides a way to Unit Test HTTP calls called $httpBackend. Essentially it is a dummy HTTP server, but it doesn't actually go over HTTP (all requests stay in memory). This is possible because the Angular Team view testability as a priority and designed it this way from the ground up.
I don't think the node-rest-client provides a similar sort of mock HTTP server so it may prove difficult to Unit Test your client. The best approach is probably to wrap all usages of the node-rest-client in a standalone javascript object which itself has no Unit Tests, but is easy to mock out in unit tests for other parts of your client side code. This un-unit tested object can then be tested against a dummy HTTP server as part of a separate test suite, or you could even rely on your Integration Tests to catch any problems with this part.
As always though, it is best to keep your reliance on Integration Tests (which connect to an actual instance of the back end) to a minimum as they are slow and unreliable. These tests should really only be for verifying top level details such as performance, connection details, configuration compatibility etc.
If you take the wrapping approach, it is important to have as little logic in the wrapper as possible, because it will not be Unit Tested!
Note that wrapping all HTTP calls in a javascript service object is probably good practice regardless of your testing strategy, as it will confine all usages of the node-rest-client to one place in your code.
Related
Currently at my place we are using protractor to write Angular e2e tests. One of the most time consuming and tedious steps is to write out all the network request/response to be EXACTLY like what you would expect. So when a page makes 5 api calls to our backend, I usually have to inspect from Chrome's network tab and copy the data one by one. I am wondering if there is a more elegant solution?
IMHO it's not a matter of testing, but the way how API is implemented.
If I understood you well you're sending 5 requests to the same endpoint (correct me if I'm wrong).
Maybe it's possible to pass an array with data to that endpoint. If it's like that, maybe it's more efficient to send one request instead of five?
If not - the only way you could do is loop over requests.
I have a Javascript application that consists of client-side code and server-side (Node/Express) code. Is there a testing solution that covers both client and server, or do you have to run seperate test frameworks for each?
Reason I ask is because I am trying to share code between client and server, e.g. a helper function that generates a unique id. Is this a good idea, or is it better to separate the concerns?
This is a complicated question with multiple answers. tl;dr You can do a lot of testing server side, but usually at some point you end up wanting client side tests.
In many respects, even though javascript applications can be isomorphic, the actual execution environment of client side vs. server side is very different when it comes to globals and language features. To be a completionist on testing-- one would need to have both client side and server side testing.
From a more pragmatic standpoint-- depending on the implementation and modularity of the javascript application one can choose to minimize or eliminate entirely the client side testing with the following methods:
- Use jsdom to replace the DOM api in node
- For isomorphic React applications use jest + react-addons-test-utils and/or enzyme as test harnesses into component instances
- Stub out browser globals as needed and test modules in isolation
At some point though, you almost always want to spin up a browser for "real world" testing. This could come in the form of holistic solutions like karma or rolling your own with mocha + browserify/webpack for units tests or nightwatch for integration / acceptance tests.
Besides the browser globals, the other important distinction between server side and client side tests is that server side tests never have any dynamic behavior. That lives entirely in the client. To the amount your application depends on browser features, rather than isomorphic library features (e.g. pure React) then you will find a greater and greater need for client side testing.
I don't know if I'm asking too much, but I want a library to intercept/mock HTTP requests in a isomorphic/progressive way (i.e. works the same on node.js and browser) for unit/behavior tests. Is there such a thing?
I'm building a client for an API and it must work both on server and browser. Nock is great but only for Node (as it doesn't work with Browserify, I tried).
I could just mock the library I'll use for requests (such as superagent or rest). That, however, would lock me in to some library and would require a major refactor of the tests.
My wish is to avoid duplication of tests and avoid the most checks for environment as possible. And to be agnostic of implementation, hence my need to mock the requests.
I'm almost considering making one myself (or at least a glue between two libraries).
I looked at how superagent were doing their tests. They build a mock Express server to respond in the way they want and check for matches.
But how does that work on the browser?
It turns out they were using Zuul for that.
Zuul is a tool that creates an ad-hoc server to run tests in the browser. It supports qunit, mocha, tape and a few other test frameworks. It also accept a mock server to run during the tests. And it runs tests on Sauce Labs, which have a free plan for open source projects.
This is not the solution I expected but it is a solution.
You can look at my project to see the proper code (permalink to the tree of the last commit by the time of this answer).
I am developing an Angular app (Angular 1.1.5). I need some way of mocking REST API responses for e2e tests.
AngularJS (Green & Seshadri) goes into some detail on unit testing HTTP requests with $httpBackend, but has little to say about e2e tests.
The documentation suggests using the ngMockE2E module to mock $httpBackend (which is distinct from the normal unit testing $httpBackend mock.
I spent a few hours investigating the ngMockE2EAPI and, whilst I can see some benefits, there seem to be many downsides. My question is:
What are the advantages of ngMockE2E over a simple server that provides test responses? or, more generally, What is the best way to test an Angular app's interactions with a server?
I can think of a few disadvantages:
I need to change my HTML to bootstrap the app with a different Angular module (a new one that depends on ngMockE2E and my actual application module)
There are no HTTP requests for Firebug/Developer tools to inspect. This is a big one for me. I ended up writing request/response logging methods in my mock backend. I guess most mock back ends contain this kind of code.
There isn't an easy way to extract parameters from URLs. If I wanted to the get the id parameter from /resource/:id, I'd need to give a regex to match the URL (\/resource\/.+$), then split the matching URL string on slash and pick the last element.
The API is clunky. Returning a static object is simple, but dynamically determining which test object to return based on the requested URL is difficult. Some apps may be able to hard-code a complete set of test URLs, but I need to test a large number of resources so this is impractical for me. More complex code means there is more to go wrong.
I can also think of some advantages. When using ngMockE2E:
I don't need to tell my app where the test API is - $httpBackend will inspect all HTTP requests for matches.
I don't need to run a web server at all.
I don't need to restart a server to pick up changes to my test data.
There are fewer overall components in the tests. However, given that this is an integration test, this isn't a huge benefit.
Very interested in thoughts and experiences.
My conclusion, several weeks of development later: I found a simple dummy backend (Node/Express) more flexible and maintanable than the e2e testing mock backend. The most compelling reasons are proper URL pattern matching and real HTTP requests for browser debugging.
I'm developing an Webapp.
It consists of 2 parts. A node rest server and an angularjs client.
The app is structured this way: Rest Server <--> Api Module <--> Angular App
The server is currently well tested.
I have Unit Tests and Integration Tests.
The Integration Tests are accessing a real database and calling the rest api over http.
I think this is as high level as it can get for the server testing.
The integration tests run fast, too.
I'm pretty confident that the way I tested the server is sufficient for my use case and I'm happy with the results.
However I'm struggling how to test the angularjs app.
I have unit tests for the relevant directives and modules. Writing these wasn't an issue.
I would like to write integration tests that cover user scenarios.
Something like a signup scenario: The user visits the website, goes to the signup form, and submits the form with the data.
The angularjs team is moving from ng-scenarios to protractor.
Protractor is using Selenium to run the tests.
Therefore there are two scopes: The app scope and the test scope.
Now I can think of three different abstractions I could use.
And I'm not sure which one suites me best.
Mock the Api Module
Mock the Rest Server
Use the full server
Mock the Api Module
In this case I would need not to setup a server. All Interactions are running in the browser
Advantage:
No server is needed
Disadvantage:
The api is in the browser scope and I have to tamper with this.
I really like this solution, but I find it difficult to mock the Api.
The Api needs to be modified in the browsers scope.
Therefore I need to send the modification from the test to the browser.
This can be done, however I don't see how I could run assertions like mockedApi.method.wasCalledOnce() in the tests scope
Mock the Rest Server
Advantage:
Client would be unchanged
Only one scope to deal with
Disadvantage:
One has to setup the Rest Routes
I could create a complete Mock Rest Server in nodejs.
Protractor Tests are written in nodejs, thus the control of the server can be done in the test.
Before I run the test I can tell the server how to respond.
Something like this: server.onRequest({method: 'GET', url: '/'}).respondWith('hello world')
Then I could do assertions like wasCalledOnce
Use the full Server with Database
Each test is running with a complete server and can add elements to the database.
After each test one can look at the expected elements in the database
Advantage:
Can be pretty sure, that if these tests are running the app is functional in the tested use case
Disadvantage:
I already made a fairly intense integration test with the rest server. This feels like doing the same again.
Setup depends on the full server
Current Conclusion
Mocking the Api would separate the server and the client completely.
Using a Mock Api would be a higher level test, but would require a fake server
Doing a full integration test would give the best reliability, but this is also highly dependant on the server code
What should I pick? What would you do?
I think I answered this same question in the Protractor google group. I am much of the same mind as you about wanting no server but wanting all of my test code in one place (in Protractor) and not split between Protractor and the browser. To enable this, I took matters into my own hand and developed a proxy for the $httpBackend service which runs within Protractor. It allows one to configure the $httpBackend service as if it were running in Protractor. I have been working on it for a while now and its reasonably full featured at this point. It would be great if you could take a look and let me know if I am missing anything important.
https://github.com/kbaltrinic/http-backend-proxy
It is an excellent question, which has nothing to do with a particular tool. I had to face the same problem on a big "greenfield" (ie started from scratch) project.
There is a problem of vocabulary here : the word "mock" is used everywhere, and what you called "integration test" are more "full end-to-end automated functional testing". No offence here, it's just that a clear wording will help to solve the problem.
You actually suggested the correct answer yourself : #2 stub the rest server. #1 is feseable but will be soon too hard to develop and maintain, #3 is an excellent idea but has nothing to do with UI testing and UI validation.
To achieve a high reliability of your front-end, independently of your backend, just stub the rest server, i.e. develop a stupid simple REST server that will idempotent, i. e. will ALWAYS answer the same thing to one http request. Keeping the idempotence principle will make development and test, very, very easier than any other option.
Then for one test, you only check what is displayed on the screen (test the top) and what is send to the server (test the bottom), so that the full UI stack is tested only once.
The full answer to the question should deserve an entire blog article, but I hope you can feel what to do from what I suggest.
Best regards
Here is an approach for writing integration tests for your Angular code. The key concept is to structure your code in a way that lets you invoke the various functions in a way very similar to how it's consumed by the UI. Properly decoupling your code is important to be successful at this though:
More here: http://www.syntaxsuccess.com/viewarticle/angular-integration-tests
This is a great question. This is how I would do it:
As you already have the angular unit tests for the relevant directives and modules this is perfect.
The other thing that is perfect is that your server Integration Tests are accessing a real database and are also making sure the rest api over http works.
So why not just add some high level integration tests that include angular and your server at the same time.
If you can avoid mocking, why not save the work to maintain the extra code, if possible.
Also a good read: http://blog.ericbmerritt.com/2014/03/25/mocking-is-evil.html
Mocking the REST server is the best, cleaner option in my opinion. Try Mountebank (http://www.mbtest.org). An amazing Virtualization Service tool.