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.
Related
So in an ideal world both client side validation and server side validation can be defined in one place, so the validation only has to be written once and can be reused where ever.
The idea i have to solve this is to do all the validation through an API using ASP.NET Core. When the form data on the client changes it will send an AJAX request with the updated data model, which the API validates and in turn returns any possible errors. The client then shows these errors to the user directly.
This way it still looks like the good old client-side validation, but it actually all happens on the server.
I can already imagine the server load is going to be increased since a lot more API calls will be send, however the question is:
will this server load be manageable in for example a big enterprise application with huge forms and complex validation?
And are there any other big drawbacks of this solution which i have to watch out for?
You are talking about an API not any other type of application with a back-end.
In this world, yes the validation of the payloads is important and needs to happen on the API side. In a way, the validation is the easiest part and less resource consuming since this is the first thing you check and if it doesn't pass then the API returns a 400 BadRequest HTTP code and nothing else happens.
There are systems where the validation, especially business rules validation does not happen on the API side. You could have for example a financial platform and the API is simply the gateway inside that world. In this case, the API acts as a pass-through and doesn't do much itself.
This being said, everything is susceptible to too much traffic, but you should be able to either throw enough resources at it, or have it deployed in the cloud and let it scale based on demand. You can load test APIs as well, to see how well they do under pressure, you must have an idea of how many calls you can expect in a certain period of time.
I wouldn't worry too much about it, I'd say validate what you can client side, so you don't even hit the API if there is no need for it and leave the rest to the API
I'm a beginner to test axios calls and started using axios-mock-adapter but I don't get why we use axios-mock-adapter.
mock.onPost('/api').reply(200, userData, headers);
In this code snippet, does the request really go to the server or is this just a simulation?
Because if I give wrong credentials, it responses with 200 status as I identify it on 'reply' to return 200.
So if I identify the response status, what is the reason to use it?
If it doesn't really go to server, it seems like this is useless.
Maybe I miss something I don't know because I'm new but someone should put the light on this issue on my mind.
Answers to your questions
In this code snippet, does the request really go to the server or is this just a simulation?
It is just a simulation. No request is made, just the "reply" is returned. This is called mocking and is hugely popular and useful for writing tests.
If you are new to different kinds of testing in general, this answer is well worth reading.
If it doesn't really go to server, it seems like this is useless.
If you want to test the system as a whole: i.e. your website + backend logic (like auth, data retrieval etc.) then yes, this is useless. But you would not use a mock for that.
Integration tests typically are executed against a running system, they are valuable, but very hard to maintain and are generally slower to execute. You have to take care of not just your tests, but even the data.
When would you use a mock
Mocks are essential for unit testing your code. Mocks help isolate your front end code logic from the dynamic behavior. This makes it easier for you to simulate many scenarios without the overhead of maintaining data.
Example Scenario
Use Case
In your application, you have to authenticate a user against a REST end point. It is expected that:
When user is logged in successfully, Logout button is shown in the header.
When users password has expired, a "change your password" screen is shown.
When user has entered wrong credentials, a warning is shown
When backend is not responding user is shown a screen to try again later
Without mocks, you need to ensure that you have the exact data configured in your authentication system. From experience I can tell you it is hard, especially #2 & #4.
But with mocks, you can just configure the mock to return the response you expect for each scenarios, in/before each it() block.
This is also easier to maintain as expectation (assert/expect statements) is set near the test data (mock.reply()).
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.
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.
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.