Unit testing jQuery getJSON function errors with the fail method, using Jasmine and Karma











up vote
0
down vote

favorite












I've written a unit test for a function that calls the jQuery getJSON method. The only thing that I'm testing is that it is called with the expected URL. My unit test uses a Jasmine Spy to mock the API call. However, when I run my unit tests I get this error:



1) should make a request to the expected URL when running on localhost
test module getDataFromApi function
TypeError: Cannot read property 'fail' of undefined


In my unit test I've created a Jasmine Spy, which returns the done and fail methods. What am I doing wrong here?



Here is my unit test:



describe('getFundDataFromApi function', function () {
beforeEach(function () {
spyOn($, "getJSON").and.callFake(function () {
return {
done: function () {},
fail: function () {}
};
});
});
it('should make a request to the expected URL when running on localhost', function () {
var expectedUrl = '/assets/mock-data/mock-data.json';
module.getDataFromApi();
expect($.getJSON).toHaveBeenCalled();
expect($.getJSON).toHaveBeenCalledWith({url:expectedUrl});
});
});


Function I'm trying to test: getDataFromApi



getDataFromApi: function () {
var mod = this;
var url = this.settings.apiUrl;

$.getJSON({
url: url
})
.done(function (data) {
mod.processApiData(data);
})
.fail(function () {
mod.displayErrorMessage();
});
},









share|improve this question




























    up vote
    0
    down vote

    favorite












    I've written a unit test for a function that calls the jQuery getJSON method. The only thing that I'm testing is that it is called with the expected URL. My unit test uses a Jasmine Spy to mock the API call. However, when I run my unit tests I get this error:



    1) should make a request to the expected URL when running on localhost
    test module getDataFromApi function
    TypeError: Cannot read property 'fail' of undefined


    In my unit test I've created a Jasmine Spy, which returns the done and fail methods. What am I doing wrong here?



    Here is my unit test:



    describe('getFundDataFromApi function', function () {
    beforeEach(function () {
    spyOn($, "getJSON").and.callFake(function () {
    return {
    done: function () {},
    fail: function () {}
    };
    });
    });
    it('should make a request to the expected URL when running on localhost', function () {
    var expectedUrl = '/assets/mock-data/mock-data.json';
    module.getDataFromApi();
    expect($.getJSON).toHaveBeenCalled();
    expect($.getJSON).toHaveBeenCalledWith({url:expectedUrl});
    });
    });


    Function I'm trying to test: getDataFromApi



    getDataFromApi: function () {
    var mod = this;
    var url = this.settings.apiUrl;

    $.getJSON({
    url: url
    })
    .done(function (data) {
    mod.processApiData(data);
    })
    .fail(function () {
    mod.displayErrorMessage();
    });
    },









    share|improve this question


























      up vote
      0
      down vote

      favorite









      up vote
      0
      down vote

      favorite











      I've written a unit test for a function that calls the jQuery getJSON method. The only thing that I'm testing is that it is called with the expected URL. My unit test uses a Jasmine Spy to mock the API call. However, when I run my unit tests I get this error:



      1) should make a request to the expected URL when running on localhost
      test module getDataFromApi function
      TypeError: Cannot read property 'fail' of undefined


      In my unit test I've created a Jasmine Spy, which returns the done and fail methods. What am I doing wrong here?



      Here is my unit test:



      describe('getFundDataFromApi function', function () {
      beforeEach(function () {
      spyOn($, "getJSON").and.callFake(function () {
      return {
      done: function () {},
      fail: function () {}
      };
      });
      });
      it('should make a request to the expected URL when running on localhost', function () {
      var expectedUrl = '/assets/mock-data/mock-data.json';
      module.getDataFromApi();
      expect($.getJSON).toHaveBeenCalled();
      expect($.getJSON).toHaveBeenCalledWith({url:expectedUrl});
      });
      });


      Function I'm trying to test: getDataFromApi



      getDataFromApi: function () {
      var mod = this;
      var url = this.settings.apiUrl;

      $.getJSON({
      url: url
      })
      .done(function (data) {
      mod.processApiData(data);
      })
      .fail(function () {
      mod.displayErrorMessage();
      });
      },









      share|improve this question















      I've written a unit test for a function that calls the jQuery getJSON method. The only thing that I'm testing is that it is called with the expected URL. My unit test uses a Jasmine Spy to mock the API call. However, when I run my unit tests I get this error:



      1) should make a request to the expected URL when running on localhost
      test module getDataFromApi function
      TypeError: Cannot read property 'fail' of undefined


      In my unit test I've created a Jasmine Spy, which returns the done and fail methods. What am I doing wrong here?



      Here is my unit test:



      describe('getFundDataFromApi function', function () {
      beforeEach(function () {
      spyOn($, "getJSON").and.callFake(function () {
      return {
      done: function () {},
      fail: function () {}
      };
      });
      });
      it('should make a request to the expected URL when running on localhost', function () {
      var expectedUrl = '/assets/mock-data/mock-data.json';
      module.getDataFromApi();
      expect($.getJSON).toHaveBeenCalled();
      expect($.getJSON).toHaveBeenCalledWith({url:expectedUrl});
      });
      });


      Function I'm trying to test: getDataFromApi



      getDataFromApi: function () {
      var mod = this;
      var url = this.settings.apiUrl;

      $.getJSON({
      url: url
      })
      .done(function (data) {
      mod.processApiData(data);
      })
      .fail(function () {
      mod.displayErrorMessage();
      });
      },






      javascript unit-testing jasmine karma-jasmine






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited yesterday

























      asked 2 days ago









      shrewdbeans

      4,113154987




      4,113154987
























          1 Answer
          1






          active

          oldest

          votes

















          up vote
          1
          down vote



          accepted










          In your function getDataFromApi you are chaining the call of fail after done but, in the mocked version of done, it returns nothing(undefined), so, you get TypeError: Cannot read property 'fail' of undefined.



          You can make the done function to return an object with a fail property that is a function.



          beforeEach(function() {
          spyOn($, "getJSON").and.callFake(function() {
          return {
          done: function() {
          return { fail: function() {} };
          }
          };
          });
          });


          Or, one line ES6 version
          spyOn($, "getJSON").and.callFake(() => ({ done: () => ({fail: () => {}}) }));



          Or, if you are planning to do more in your tests, like testing success or failed responses, probably returning a jQuery Deferred can help you



          beforeEach(function() {
          spyOn($, "getJSON").and.callFake(function() {
          const deferred = $.Deferred();

          deferred.resolve({'success': true});

          return deferred;
          });
          });


          Calling deferred.reject({'success': false}); will give you the chance to test for errors.



          Hope it helps






          share|improve this answer





















            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














             

            draft saved


            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53392072%2funit-testing-jquery-getjson-function-errors-with-the-fail-method-using-jasmine%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            1
            down vote



            accepted










            In your function getDataFromApi you are chaining the call of fail after done but, in the mocked version of done, it returns nothing(undefined), so, you get TypeError: Cannot read property 'fail' of undefined.



            You can make the done function to return an object with a fail property that is a function.



            beforeEach(function() {
            spyOn($, "getJSON").and.callFake(function() {
            return {
            done: function() {
            return { fail: function() {} };
            }
            };
            });
            });


            Or, one line ES6 version
            spyOn($, "getJSON").and.callFake(() => ({ done: () => ({fail: () => {}}) }));



            Or, if you are planning to do more in your tests, like testing success or failed responses, probably returning a jQuery Deferred can help you



            beforeEach(function() {
            spyOn($, "getJSON").and.callFake(function() {
            const deferred = $.Deferred();

            deferred.resolve({'success': true});

            return deferred;
            });
            });


            Calling deferred.reject({'success': false}); will give you the chance to test for errors.



            Hope it helps






            share|improve this answer

























              up vote
              1
              down vote



              accepted










              In your function getDataFromApi you are chaining the call of fail after done but, in the mocked version of done, it returns nothing(undefined), so, you get TypeError: Cannot read property 'fail' of undefined.



              You can make the done function to return an object with a fail property that is a function.



              beforeEach(function() {
              spyOn($, "getJSON").and.callFake(function() {
              return {
              done: function() {
              return { fail: function() {} };
              }
              };
              });
              });


              Or, one line ES6 version
              spyOn($, "getJSON").and.callFake(() => ({ done: () => ({fail: () => {}}) }));



              Or, if you are planning to do more in your tests, like testing success or failed responses, probably returning a jQuery Deferred can help you



              beforeEach(function() {
              spyOn($, "getJSON").and.callFake(function() {
              const deferred = $.Deferred();

              deferred.resolve({'success': true});

              return deferred;
              });
              });


              Calling deferred.reject({'success': false}); will give you the chance to test for errors.



              Hope it helps






              share|improve this answer























                up vote
                1
                down vote



                accepted







                up vote
                1
                down vote



                accepted






                In your function getDataFromApi you are chaining the call of fail after done but, in the mocked version of done, it returns nothing(undefined), so, you get TypeError: Cannot read property 'fail' of undefined.



                You can make the done function to return an object with a fail property that is a function.



                beforeEach(function() {
                spyOn($, "getJSON").and.callFake(function() {
                return {
                done: function() {
                return { fail: function() {} };
                }
                };
                });
                });


                Or, one line ES6 version
                spyOn($, "getJSON").and.callFake(() => ({ done: () => ({fail: () => {}}) }));



                Or, if you are planning to do more in your tests, like testing success or failed responses, probably returning a jQuery Deferred can help you



                beforeEach(function() {
                spyOn($, "getJSON").and.callFake(function() {
                const deferred = $.Deferred();

                deferred.resolve({'success': true});

                return deferred;
                });
                });


                Calling deferred.reject({'success': false}); will give you the chance to test for errors.



                Hope it helps






                share|improve this answer












                In your function getDataFromApi you are chaining the call of fail after done but, in the mocked version of done, it returns nothing(undefined), so, you get TypeError: Cannot read property 'fail' of undefined.



                You can make the done function to return an object with a fail property that is a function.



                beforeEach(function() {
                spyOn($, "getJSON").and.callFake(function() {
                return {
                done: function() {
                return { fail: function() {} };
                }
                };
                });
                });


                Or, one line ES6 version
                spyOn($, "getJSON").and.callFake(() => ({ done: () => ({fail: () => {}}) }));



                Or, if you are planning to do more in your tests, like testing success or failed responses, probably returning a jQuery Deferred can help you



                beforeEach(function() {
                spyOn($, "getJSON").and.callFake(function() {
                const deferred = $.Deferred();

                deferred.resolve({'success': true});

                return deferred;
                });
                });


                Calling deferred.reject({'success': false}); will give you the chance to test for errors.



                Hope it helps







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered 2 days ago









                Castro Roy

                3,765115186




                3,765115186






























                     

                    draft saved


                    draft discarded



















































                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53392072%2funit-testing-jquery-getjson-function-errors-with-the-fail-method-using-jasmine%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    A CLEAN and SIMPLE way to add appendices to Table of Contents and bookmarks

                    Calculate evaluation metrics using cross_val_predict sklearn

                    Insert data from modal to MySQL (multiple modal on website)