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

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.

Related

Unit testing on an Angular app with Karma

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.

Orchestrating Non-JavaScript Backend from Protractor Test

I am writing an application which has a LAMP backend, which provides a RESTful API. This API is consumed by an AngularJS front-end.
I have unit and integration tests for the API / GUI in isolation. Now I am expanding my test horizon to encompass a full front-to-back test suite.
I've been playing around with Protractor, which has been extremely useful for the browser-based inputs for my front-to-back tests.
However, I'm strugging to see how I can integrate this with the orchestration of the PHP backend.
Within the PHP integration tests, I have a set of utility classes that populate the system (i.e. database) with a pre-determined universe. For example; there is a pre-created user called "Bob", and an administrator called "Alice".
Between each integration test case, the entire universe is re-set to this base state, so that any interactions with Bob & Alice in the test are re-set.
This is one example of the orchestration I would like to manage from Protractor. However, I cannot see an easy pattern to integrate with the PHP code which constructs the test universe.
After the initial population of the world, there are other orchestration tasks I would like to be able to execute to get the system into the desired target state; e.g. locking Bob's user account.
Without wanting to access the MySQL DB directly from the protractor code, how can I re-use my PHP logic and invoke the business logic from Protractor?
I could offer RESTful orchestration URLs. But this seems dangerous, as it would pose a serious risk if ever released to production.
There are a number of suggestions on other StackOverflow questions (e.g. this one) which suggest using Mocks. These seem to completely miss the mark; given protractor is designed for front-to-back tests.
Business Logic
We have done that but in a different way. We have written that business logic in our API service code that it will check what kind of environment you are trying to reset. If your target environment is your local codebase or test environment then it will offer your Rest /reset apis.
if(environment === qa || environment === local) {
// Allow reset service
}
else {
// No reset service
}

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.

Unit Testing the Server Interface for a Silverlight-Facebook Application

I have a Silverlight 4 client running on a Facebook page hosted on Google App Engine. It's using gminifb to communicate with the Facebook API. The Silverlight client uses POST calls to the URIs for each method and passes the session information from Facebook with each call.
The project's growing and it would be super-useful if I could set up a unit-testing system to make a variety of the server calls so that when I make changes I can ensure everything else still works. I've worked with nUnit before and I like what I've read of PEX but I'm not sure how to apply them to this situation.
What're the choices for creating a test system for this? Pros/cons of each?
How do I get started setting something like this up?
Solved. I did it as follows:
Created a special user account to be used for testing on the server that bypassed the authentication. Only did this on the test environment by checking a debug flag in that environment's settings. This avoided creating any security hole in the live site (since the same debug flag will be false there.)
Created a C#.NET solution to test each API call. The host project is a console app (no need for a GUI) with three reusable synchronous methods:
SendFormRequest(WebRequest request, Dictionary<string,string> pairs),
GetJsonFromResponse(HttpWebResponse response),
and ResetAccount().
These three methods allow the host project to make HTTP requests on the server and to read the JSON responses.
Wrapped each server API call inside a method call in the host project.
Created an nUnit test project in the solution. Then simply created tests that call each wrapper method in the host project, using different parameters and changing values on the server.
Created a series of tests to verify correct error handling for invalid parameters and data.
It's working perfectly and has already identified a few minor issues that have been found. The result is immensely useful and will check for breaking changes on new deployments.

Resources