What is the purpose of using a mock ajax call in testing? - javascript

I'm learning about TDD React here and don't understand the below test situation:
it('Correctly updates the state after AJAX call in `componentDidMount` was made', (done) => {
nock('https://api.github.com')
.get('/users')
.reply(200, [
{ 'name': 'Reign', 'age': 26 }
]);
// Overwrite, so we can correctly reason about the count number
// Don't want shared state
wrapper = mount(<UsersListComponent />);
setTimeout(function() {
expect(wrapper.state().usersList).to.be.instanceof(Array);
expect(wrapper.state().usersList.length).to.equal(1);
expect(wrapper.state().usersList[0].name).to.equal('Reign');
expect(wrapper.state().usersList[0].age).to.equal(26);
nock.cleanAll();
done();
}, 1500);
});
What is the purpose of using nock to fake a request? This request doesn't do anything and I'm not sure where the response goes to. I thought TDD approach is to write the test (the code starting at wrapper), see it fail, and then use a real ajax call in the actual component to test. I don't see what nock does here.

The purpose of the nock call in your code is to fake an API request. Nock captures / intercepts the call and instead of the actual response it returns a response with fake information.
The title of the test is Correctly updates the state after AJAX call... so the intention is to test whether the state is updated correctly, and not whether the actual API request has been successfully carried out.
This allows you to model and test different scenarios, for example, how your app behaves when receiving different datasets. It also allows you to complete your tests when the actual API may not be ready yet.

The purpose of Unit Testing is to be only testing your code is the most isolated way possible. Faking an AJAX request and getting its responses is a very common practice to avoid issues with your endpoint (since this is not what you are testing anyway) and focusing on the code handling the response of this endpoint, and you can choose different models of response to test different scenarios.
Nock will simply feed the response back to your component when your call to 'https://api.github.com/users' is made

Related

How to make only one API request when using React SSR?

My application has to make an API call, that returns an array of items that gets styled and rendered to the screen. To make my SSR rendering work, I have to make the API request on server of course, but when using the SSR you also have to rerender (using ReactDOM.hydrate) on the client and I'm making the 2nd API request in here.
Since the API request takes more than 2 seconds, doing it 2 times is so inefficient. Is there a workaround around that by only doing 1 request and someway using the data on both server and client?
This is how you fetch data on a server and reuse it on client - straight from the redux documentation. If you are not using redux you will need to implement something very similar.
To answer the latter question - how to avoid making another request on the client? You just need to check if the data is there :)
componentDidMount() {
if(!this.props.isDataFetched) {
this.props.fetchData();
}
}
or maybe...
componentDidMount() {
if(this.props.data.length === 0) {
this.props.fetchData();
}
}

SOCKET.IO analogy in angular application (with rx.js)

I am developing angular(2) application.
And I want to update view when data changed in back end.
getData() {
return this.http.get("some url")
.map(result => result.json());
}
How can I develop listener in my component, which will be listen and updating view?
So, two solutions depending on what you are able to do:
1 - You have write access to the server's code
Then you can implement the websocket support on your server and then use a tool like https://github.com/ohjames/rxjs-websockets to automatically wrap the socket events in rxjs observables.
2 - You don't have write access to the server's code
Well, in this case, you will have to do a regular polling of the server. Which would look something like that:
Rx
.Observable
.timer(0, 1000) // once every second
.mergeMap(_ => this.http.get("/url").map(json => result.json()))
If the server is well implemented (and you send the right headers), it might send you back a 304 http code from which you can deduce that nothing happened since your last call, and you can filter out those cases.
Hope it helps

Why does sinon fakeserver not reply to request from Vue component

I am chasing a race condition since days now. I am really glad for any help. This is both a sinon fakeserver and a Vue.js related question.
Here is the setup of my little project:
The project is based on the awesome vue webpack template.
I have a rather elaborate vue component called DoogieTable that shows a table. It can load data from a remote REST endpoint. (using vue-resource)
I have a mocha test case for DoogieTable. The second test about loading remote data into the table is my problem.
The test mocks the xHhtmlRequest with sinon.fakeServer and responds with canned data.
This works as long as I set fakeServer.autoRespond = true; But according to the sinon doc, this is not suitable for production ready unit tests.
When/Where in the code of my test case do I have to call fakeServer.respond() ?
Things I already tried:
Calling it right after the the vue component DoogieTable became ready => that seems to be to early. At that point in time, the request to load data has not been send by the component. (I think. I am not quite sure)
Calling in a vm.$nextTick callback => same problem. No request yet.

When using Jasmine's exceptGET / $httpBackend, what's the benefit of having .respond()?

I am using the book called AngularJS Up and Running. It gives an example of using exceptGET. This is the example:
mockBackend = $httpBackend;
mockBackend.exceptGET('/api/note')
.respond([{id:1, label: 'Mock'}]);
My question is, isn't the point of unittesting server calls to make the server call and verify that the server call is what we expect it to be?
With the above code, does it not just make a server call and force the response to equal [{id:1, label: 'Mock'}]? What's the point of doing it if we aren't able to check what the actual response is?
Because later on in the code, it checks the response like so:
mockBackend.flush();
expect(ctrl.items).toEqual([{id:1, label: 'Mock'}]);
Wouldn't it Always equal [{id:1, label: 'Mock'}] because that's what we forced the response to equal? What's the benefit of having .respond() and controlling the response?
If you would actually hit an API endpoint on the server in your unit test, it would not be a unit test anymore - it would now involve much more than just your component under test (controller/service/provider etc) - the network, the web server, the backend itself, probably a database etc - now this becomes an integration test or a system/functional test.
Your unit test would not be isolated anymore and would depend on more things than it should. The point of mocking is to make the test isolated, independent and imitate certain desired conditions - in this case an HTTP response - and then check how your component under test would react.
expect(ctrl.items).toEqual([{id:1, label: 'Mock'}]);
This expect call itself, at least, would check that the mock was successfully applied and the items controller variable contains the mocked response.
Please see more at:
Unit tests vs Functional tests
What is Mocking?

backbone model fetch - mock back-end

I have a model and I am trying to fetch it using model.fetch();. The model's urlRoot set to the back-end of my application ("/backend/item"), but right now I don't have the back-end environment. So I decided to mock the results. I added a route inside my router:
"backend/item/:id": "data_getItem"
and a function:
data_getItem: function(id) {
console.log("data_getItem: "+ id);
return {
animals: [
{
name: 'flying cat',
type: 'none'
}
]
};
}
When running the application I can see ajax call to "http://127.0.0.1:8000/backend/item/1" but the console is empty and I get an error (the fetch function returns me to the error callback). Why is that? How can I mock the back-end?
EDIT
Actually #rjz helped me with the things I want to do, but I really want to know if an ajax call can be catched by backbone router.
My intuition tells me not because ajax call cannot execute backbone client code and therefore the router concept is not relevant. Am I right?..
I don't think you want to use a Backbone.Router to catch your AJAX calls. If your goal is mocking out the backend of your project, you should use a testing framework to do this. A down and dirty way would be to use something like:
mock-ajax
jquery-mockajax
or if you want to do something more like unit testing I would look at Jasmine and its AJAX mocking library.
Update to answer your question:
The short answer is no, a Backbone.Router cannot intercept AJAX calls.
This is because the router works by listening to events that have to do with the URL. Specifically, the router is listening to the hashchange or popstate events (depending on if you are using pushState). Since AJAX calls do no interact with the URL they pretty much totally bypass this system.

Categories

Resources