Have I got it all wrong with the way Controllers communicate with Services and how I conduct unit testing?

Currently, I am in the process of developing an AngularJS application and I want to ensure it follows best practices. When making external API calls using either $resource or $http, I always do this within a separate Service or Factory. However, I am unsure about the best approach for retrieving the returned value from the Service in the calling Controller.

The method I currently use is as follows:

  1. The Controller initiates the call to the Service
  2. The Service executes the $http request and checks the promise.
  3. If the promise is successful, the Service sends out an event with the returned object.
  4. The Controller listens for that event and performs necessary operations.

While this method works well and allows me to reuse the same event for different requests (e.g. displaying new messages after fetching all messages or posting a message), I have recently decided to implement testing procedures in my application.

When conducting unit tests on my Controllers, I aim to mock certain Services to return specific values. However, since my Services trigger events rather than returning values directly, I anticipate challenges in checking the "return" values of the Services during testing.

Therefore, I am seeking opinions on whether I may have overlooked something in my approach. Is it advisable to retrieve promises directly into Controllers when invoking Services? Would this be a more effective or efficient way to handle such scenarios?

While I understand that each application has its unique logic, I believe that in AngularJS, adhering to specific set of choices and best practices is crucial for maintaining modularity and testability.

Any suggestions or insights would be greatly appreciated.

Answer №1

Without reviewing the specifics of your code, here are some suggestions:

You can have your controller handle the promise directly without needing to broadcast it. Simply have your controller receive the promise from the service call using $http and then execute the necessary actions once the promise is resolved.

When testing functions in a service that do not return anything, you can utilize spyOn to verify that the function has been called. In this case, what matters in the test is confirming that the function is indeed being invoked by the controller, rather than focusing on the internal workings of the service itself.

Answer №2

It is not advisable to use events for this type of interaction as they can create chaos in the code and make it harder to maintain. While there are some situations where events may be useful, using promises is generally a better approach.

Here are three alternative options:

  • Simply return the $http promise object and handle it within your controller
  • Create your own promise using the $q service and implement your own logic for handling the response from $http (a more flexible option than the first)
  • Pass a function callback to the services which you can then call within your service to send the result back to the controller

Avoid using events in these scenarios. For unit-testing purposes, you can configure the $httpBackend service to mock your queries. This way, you can test your controller without complicating your services by having the $httpBackend return a configured response instead of making real http calls.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

As you scroll, the opacity gradually increases, creating a dynamic visual

Struggling to replicate a feature on a website where images gain opacity as you scroll down? Check out this site for reference: . While my current code somewhat achieves this effect, I'm having trouble figuring out how to apply a darker opacity gradua ...

Is there a way to access the variable value chosen from a select dropdown inside a function and then assign it to a JavaScript variable outside of the function?

Below is the HTML and JavaScript code that I am working with: function changeResult() { x = document.getElementById("dropdown-list").value; console.log((x)); } var qq; <select id="dropdown-list" onchange="changeResult()"> <option value="4 ...

Transform the value of Material-UI DatePicker to seconds

I am trying to figure out how to convert the value from a React Material-Ui datepicker, which currently looks like this: 2021-05-26T01:30, into seconds. Any suggestions on how I can achieve this? PS: My goal is to create a schedule SMS module. Therefore, ...

Should tabs be closed or redirected after successful authentication with Google?

I have a project that was developed using perl-dancer and angular. The project is integrated with Google as an openID system. On some of the pages, there is an edit grid with a save button. To prevent loss of unsaved data when the session (created from pe ...

Having issues with Thymeleaf template not functioning properly when using inline JavaScript

I've encountered an issue when attempting to extract my function into a script within HTML. When written as shown below, it works perfectly: <input type="text" id="myInput" onkeypress="return confirm('Are you sure you want to delete ...

Is it possible to conceal my Sticky Div in MUI5 once I've scrolled to the bottom of the parent div?

Sample link to see the demonstration: https://stackblitz.com/edit/react-5xt9r5?file=demo.tsx I am looking for a way to conceal a fixed div once I reach the bottom of its parent container while scrolling down. Below is a snippet illustrating how I struct ...

Guide on sending a basic ID using jQuery AJAX to an Action method in ASP.NET MVC

I'm facing an issue with a category drop-down list where I have written the following code in its onchange event: function onChange() { $.ajax( { url: '/Home/GetProducts/', type: 'POST', data: JSON.stringify({ID:$("#Category").val ...

Guide to showcasing associated information in HTML using Angular 7

I am a beginner with Angular 7 and I am attempting to showcase a product's color on the HTML side using Angular 7 but have not been successful. Below are my tables; Product Id Name Color Id Name ProductColorRelation Id ProductId ColorId In ...

I'm experiencing an issue where a function call within a Vue.js v-for directive causes the loop to continue indefinitely, but I'm unsure of the cause

Here is the template I am working with: <template> <div> <div v-for="report in reports"> <div class="map" v-bind:id="mapID = report.started.toUpperCase()" v-text="report.started"> {{hello(mapID)}} </div& ...

Ways to deactivate the Bootstrap collapse feature

In my accordion FAQs, I am facing an issue where Question 1 is automatically opened when the page loads. Additionally, when I click on Question 2, it closes instead of staying open. I would like to address these problems and make sure that each question st ...

Extracting information from a Weather API and sharing it on Twitter

Can anyone help me troubleshoot my Twitter bot setup for tweeting out city temperatures? I attempted switching to a different API, but nothing seems to be resolving the issue. console.log('initiating twitter bot...') var Twit = require('t ...

Error: There was an issue registering the component as the target container is not recognized as a valid DOM element

Upon executing the React code below, I encountered the following error: import React from 'react'; import ReactDOM from 'react-dom'; ReactDOM.render( <div id="root"> <h1>Hello, world!</h1></div>, document ...

Modify Chartjs label color onClick while retaining hover functionality

Currently, I have implemented vue-chart-js along with the labels plugin for a donut chart. Everything is working well so far - when I click on a section of the donut chart, the background color changes as expected. However, I now want to also change the fo ...

Finding the right property by comparing it with an array of objects in a MongoDB aggregation query

In my mongoDB collection, I have a field called 'abc' that contains an array of objects structured like this: 'abc': [{"_id": new ObjectId("someId"), "name": "entity name"}] I am looking to perfo ...

Using Jquery to insert error messages that are returned by PHP using JSON

I am attempting to utilize AJAX to submit a form. I send the form to PHP which returns error messages in Json format. Everything works fine if there are no errors. However, if there are errors, I am unable to insert the error message. I am not sure why th ...

What is the best way to retrieve a variable within an AngularJS controller?

I am working with a binding parameter eid: '@' Inside my constructor, you will find the following method: this.$onInit = () => { console.log('eid: ', this.eid) } console.log("eid in another section: ", this.eid) Upon running t ...

Sorting information in the React Native Section List

Working with React Native's SectionList and filtering data: data: [ { title: "Asia", data: ["Taj Mahal", "Great Wall of China", "Petra"] }, { title: "South America", data: ["Machu Picchu", "Christ the Redeemer", "C ...

Issue with Jquery checkbox calculator constantly displaying Not a Number (NaN)

I'm facing an issue with jQuery. The Custom Wpform Checkbox Field is returning NaN. HTML <div class="wpforms-payment-total"> $ 85 </div> <input type="checkbox" name="myBox2" size="1 ...

What steps do I need to take to integrate AngularJS with the ServiceStack FallbackRoute attribute in order to enable support for HTML5 pushstate URLs?

Currently, I am in the process of developing a client/server solution which involves using an AngularJS Single Page App as the client component and a Self-Hosted ServiceStack RESTful API as the server component. The setup consists of HTML and JavaScript fi ...

Adding a hash to asset paths in NextJS static builds

After running next build && next export, I receive a directory named out, which is great. When examining the source code, such as in the index.html file, it requests assets from <link rel="preload" href="/_next/static/css/styles.aa216922.chunk. ...