Unit testing on an Angular app with Karma - angularjs

So i'm quite new with test cases and I have a small questions (specific to my case).
I am currently developing an Angular app and started to do unit test with Karma (Mocha/Chai).
The back end of this app is a node RESTful API.
So basically, the app is a bunch of controllers and services making some basic CRUD operations.
On creation of a new user for example, I handle the verification in the html form using angular's form directives. In the server side, there is also a verification on the object received.
So generally my functions on controllers are no more then things like:
create() {
UserService.create(vm.newUser).then(callBackToDisplaySuccessOrErrorMessage);
}
It will probably sounds silly, but i'm new in this domain (test cases) and i am a little bit confused, so my first question is:
since the http calls are mocked, what is the point to do unit testing in app such as mine ?
And my second question is :
how to unit test basic app like in my case in a proper way ?

To clarify your doubts:
1. Mocking is used to test the communication.
While writing spec for your controller who are more interested in verifying whether a call to userService.create is invoked with expected parameters or not. Similarly you will mock the response from service if any. So you have validated the functionality of Controller-communicating with- Service.
Now when you write spec for service, yes http calls are mocked, but still you are validating the http url, expected method to be invoked like GET, POST etc, parameters to be passed. You only mock the expected success/failure response and validate your handlers for the same.

Related

Simple camel routing from to

I have a fundamental question regarding routing in Camel. Assuming I have this following route:
from(amq:MyQueue).process("jmsToHttp4").to("http4://dummyhost:8080").to("file://out/MyFolder");
Assuming that the http4-Response is just a String "Your Response". As far as I understood the documentation, "Your Response" can be retrieved through:
exchange.getOut().getBody()
Lets say that I only want to write "file://out/MyFolder", only if the reponse contains the word "Response". How can I achive this?
One more question:
If I want to write a test in a spring environment, how can I mock the response with "Your Response positive test" and "Your negative test"? Somehow I need to be able to write the response strings in the exchange.out.body right?
Thank you,
Hadi
One option would be to declare a .filter(body().contains("Response")) right after the HTTP call.
As for the test, you might use the mock component that offers you ways of processing the exchange and also asserting whatever you need when the message hits your mock endpoint.
There is actually some alternatives to test... I'm used to declaring the endpoints in the properties file and using the key in the class, e.g. .to("{{my.http.target}}"). Thus, in this case, in the test environment (dedicated properties file) you'd replace your http4 with mock.
In my opinion, it is cleaner and requires less control of the context when writing tests, mainly in big/complex applications. On the other hand, this might affect code readability.
But if you prefer to keep declaration in your Java class, you'll have to intercept the http4 call in the test env, then divert it to your mock endpoint.
I hope it's helpful.

Testing in AngularJS : How do I test the backend response of my API's?

I am new to testing in AngularJS and just started to use testing using Karma and jasmine for a particular use case. Actually, I am a front end developer and the backend API's keep changing as the system is under migration. So I wanted to implement a test on service wherein I can catch response from the actual API and test the response where I have the same data all the time as the database is exported and is in the consistent state.
Is there a way to do it? Because all articles I have read they mock the response of the API and then test the individual methods written. Or do I have to use protractor for E2E testing?
When you run tests with karma, your backend will be mocked as soon as you load angular-mocks.js (see https://docs.angularjs.org/api/ngMock/service/$httpBackend). This is what we want because we need unit tests to run quickly without having to run a backend and database.
If you need to test the interaction between your app and the real API, you need to do E2E tests with protactor, as in this kind of test, the backend is running.
Now, if you need to test the real API output, it is - in my humble opinion - the work of the backend developer. Having that said, you can of course test it yourself, but it has nothing to do with AngularJS. I'm not a NodeJS developer but there are tools to test API endpoint. You can look at SuperTest for example wich
provide a high-level abstraction for testing HTTP
Here is an example from their documentation :
var request = require('supertest');
var express = require('express');
var app = express();
app.get('/user', function(req, res) {
res.status(200).json({ name: 'tobi' });
});
request(app)
.get('/user')
.expect('Content-Type', /json/)
.expect('Content-Length', '15')
.expect(200)
.end(function(err, res) {
if (err) throw err;
});
Many people forget that Karma is not specific to Angular. It is made to run tests on JavaScript code, regardless of the framework you may or may not use. So, you can run tests with Karma that do not use Angular or Angular Mocks and that interact with a database. These types of tests are called integration or functional tests (there's a fine line that separates the two, depending upon how you look at it) and they should be included in every project. I have seen tests of this nature use Jasmine, and I have seen them use Mocha. The choice is yours. Either way, don't expect them to run as fast as unit tests since you'll be contending with network and database latency. When you run these tests in your development cycle is up to you. Since they take longer, most times they are only run on a full build or after the API/database have changed.
All of this being said, the developers that produce the API should be the ones writing/running these tests and providing you (the customer) with updated documentation.

How can I have $http return mock data while a service endpoint is not ready?

In an Angular service (provider.service) that uses $http, is there a way to periodically turn on and off what certain calls using $http will return?
Here's my scenario: we are using $http to consume web services built by another development team. When those services are not yet ready (or break) we don't want development efforts to halt on our end. We simply need to temporarily turn off that specific call and have it return mocked data.
I've seen $httpBackend being used to mock out HTTP calls, but I'm not sure that will work for me, and if it would, I'm not sure how this would look or be configured.
If you are making your $http calls from a data service, you can set toggles in your service. Don't even make the http call if you know it will fail. Alternatively you could probably even make a whole mock data service to use at dev time, and replace it with the actual service when your backend is ready, avoiding issues of dev code being there in production. This is one of the reasons people say you should never reference $http in controllers.
See the AngularJS Style Guide - Data Services for a better explanation than I could ever write.

$httpBackend with AngularJS/Jasmine - why mock a response?

The AngularJS tutorials say that when using $httpBackend a response should be mocked. What I'm unsure about is why would I want to mock a request to an API when I could just use $http and make the request and retrieve the 'real' data? I can then run the test on the actual response, this allows to check if data response from the API has changed (for what ever reason). However, if I was mocking the response and the API data changes, then my mock response will be different to the actual response. Therefore making the tests incorrect.
You got it right. There are (at least) three types of tests:
Unit tests
Integration tests
System tests
You can find a nice explanation here.
Everybody defines those tests different. My perspective is:
Unit tests are testing a module/each function separately.
Integration tests are testing a whole workflow ("Fill out registration form > sending data to backend > receiving token >
login")
System testing - for me - is: Use cases in the Front End. Example: Can a user login and will present with the user profile after entering his credentials.
What you are describing is a Unit test. Therefore, testing if your function is performing an API call is enough. Also test if you call a certain URL and sending the correct data.
Remember: You often times run tests with every change in your code.
Therefore, it would be quite too much to always call the real API.
From the Angular docs:
During unit testing, we want our unit tests to run quickly and have no
external dependencies so we don’t want to send XHR or JSONP requests
to a real server. All we really need is to verify whether a certain
request has been sent or not, or alternatively just let the
application make requests, respond with pre-trained responses and
assert that the end result is what we expect it to be.
You can test this with $httpBackend.expect.
So, what if your API endpoint is changing the structure of the data?
Get sure you are testing the backend and get sure you send the data as defined
Write an integration test where you check the data flow through a certain process (login, receiving data for a dashboard etc.)
In the end, there is no bullet proof concept. But those steps and mentality is already a good proof for a fairly big project.
Jasmine is an unit test framework.
If you use $http directly, you won't test an unique component, you will test at the same time your API. If your API is down, your test will fail.
It is cleaner to test your components individualy.
More :
$httpbackend allows you to try test case that your API doesn't offer. So you can build robust applications.
$http can take time to resolve, when $httpbackend can resolve all the request just by asking :
httpBackend.flush();
etc.

$HTTP service in Angular.js

I am new in Angular.js, and just learning it.
I am looking on $http service to send AJAX request.
I got three ways to send AJAX request form Angular.js.
These are here
AJAX calls via the $http service.
JSONP calls via the $http service.
REST type calls.
Actually I am getting confuse to these three process, that which is better for me to use.
Which will be more efficient and reliable for me to implement it in my project?
My main aim to make it high throughput.
Any suggestion will be helpful for me.
If you are a beginner I would recommend you to go with the $http. Which is pretty straight forward and simple to use and serves most of the regular development tasks. The other two requires fair amount of understanding though they do the same job making ajax calls.

Resources