1

I'm trying to learn angular unit test with $resource.

Here I have a simple controller :

.controller('DictionaryCtrl', function ($scope, DictionaryService) {

  $scope.jSearchDictionary = function () {
    $scope.word = DictionaryService.getByJword({ jp: $scope.jword });
  }

  $scope.eSearchDictionary = function () {
    $scope.word = DictionaryService.getByEword({ eng: $scope.eword });
  }
})

In my view, I have 2 ng-submit (jSearchDictionary and eSearchDictionary) and i bind the corresponding word that is searched ( jword or eword ).

The service is also quite simple :

.factory('DictionaryService', function ($resource) {
  return $resource('http://127.0.0.1:3000/api/nlp/words', {}, {
    getByJword: { method: 'GET', params: { jp: '@jword' } },
    getByEword: { method: 'GET', params: { en: '@eword' } },
  })
})

Finally, here is my test.

describe('Controller: nlpCtrl', function () {

beforeEach(function () {
  this.addMatchers({
    toEqualData: function (expected) {
      return angular.equals(this.actual, expected);
    }
  });
});

beforeEach(module('gakusei'));

describe('nlpCtrl', function () {
var scope,
    $controller,
    $httpBackend,
    $stateParams,
    Eword,
    mockWord = [
    {
      "words": [
          {
            "readings": [
                "ホッケー"
            ]
          }
      ],
      "count": 1
    }];

beforeEach(inject(function (_$httpBackend_, $rootScope, _$controller_) {
  scope = $rootScope.$new();
  $controller = _$controller_;
  $httpBackend = _$httpBackend_;
}));

afterEach(function () {
  $httpBackend.verifyNoOutstandingExpectation();
  $httpBackend.verifyNoOutstandingRequest();
});

it('should get a word', inject(function (DictionaryService) {
  Eword = "englishWord";
  $httpBackend.expectGET('http://127.0.0.1:3000/api/nlp/words?eng=englishWord')
    .respond(mockWord[0]);

  var ctrl = $controller('DictionaryCtrl', { $scope: scope });
  var request = DictionaryService.getByEword({ eng: Eword })

  $httpBackend.flush();

  expect(scope.word).toEqualData(mockWord[0]);
  expect(BasketService.getByJword).toBeTruthy();
  expect(BasketService.getByEword).toBeTruthy();
}));
});
});

The problem is at the line :

expect(scope.word).toEqualData(mockWord[0]);

scope.word being undefined. Unit Testing is way over my head right now, I'm not sure of what I'm doing at all. If you have a solution to this particular problem, have any advices at all concerning all the code or are willing to message me and guide me a little, that would be awesome.

0

2 Answers 2

1

You have couple issues in your expectation and set up.

1) You are testing a controller and its scope, so do actions on the controller methods and set values on controller scope.

2) Instead of doing Eword = "englishWord"; you should set the value on the controller scope scope.eword = "englishWord";

3) Instead of calling service method directly DictionaryService.getByEword({ eng: Eword }) , you need to invoke the method on the scope, i.e scope.eSearchDictionary(); so that when the method is resolved it resolves with respective data and sets it on the scope.

4) Note that when you test against scope.word directly you may not get desired result since the result object will have additional properties like $promise on it. Since you are directly assigning the results.

5) I am not sure if you need the last 2 expectations at all.

Try:-

it('should get a word', inject(function (DictionaryService) {
  scope.eword = "englishWord";
  $httpBackend.expectGET('http://127.0.0.1:3000/api/nlp/words?eng=englishWord')
    .respond(mockWord[0]);

  $controller('DictionaryCtrl', { $scope: scope });

  scope.eSearchDictionary();

  $httpBackend.flush();

  expect(scope.word.words[0]).toEqual(mockWord[0].words[0]);

  /*I dont think you need the following expectations at all*/
  expect(DictionaryService.getByJword).toBeDefined();
  expect(DictionaryService.getByEword).toBeDefined();

}));

Plnkr

Some syntax of expectation utility method is different from what you are using, you can use the same that you use, i just did it for the demo

Sign up to request clarification or add additional context in comments.

2 Comments

Worked fine, thank you very much! Would that be an acceptable unit test or is there something else I should test?
@Benoit You are welcome. You could really write different test block for various scenarios you may want to test your controller, based on what you are doing. You can test jSearch dictionary as well in a differnt block. Also when you have multiple test blocks you could move common initialization stuffs to beforeEach block, eg:- resource mock, controller creation, backend mock etc..
0

The variable you are looking for does not exist outside of those two functions. Try defining it at the top of your controller like so:

.controller('DictionaryCtrl', function ($scope, DictionaryService) {

  $scope.word = '';

  $scope.jSearchDictionary = function () {
    $scope.word = DictionaryService.getByJword({ jp: $scope.jword });
  }

  $scope.eSearchDictionary = function () {
    $scope.word = DictionaryService.getByEword({ eng: $scope.eword });
  }
})

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.