1

Whenever, I am testing a controller and have something like this in it.

$scope.isSomething = function (Item) {
      return ItemCollection.someItem(Item.attachedItem);
    };

giving error on karma console:

TypeError: undefined is not an object (evaluating 'Item.attachedItem')

I am simply calling the function from the test file like this:

scope.isSomething();

I need to mock the Item.attachedItem or I am missing something here.. Please Explain in details as this is happening in multiple files.. thanks in advance

Also, for this type of code

   .controller('itemCtrl', function (itemCollection) {
        var vm = this;
        this.itemCollection= itemCollection;
     itemCollection.someItem().then(function (Item) {
          vm.pageUrl = Item.pageUrl;
          vm.Item= Item.someItems;
        });
    });

Also, this is also part of the code for more broad view here it gives Item.pageUrl is not a object error

1
  • 1
    you have to mock both ItemCollection and Item Commented Mar 10, 2016 at 12:37

3 Answers 3

2

Refer angular unit testing docs

The ItemCollection being a service, you could inject a mock while initialising a controller using

    var ItemCollection, ItemCrtl;
    beforeEach(inject(function($controller, $rootScope) {
        $scope = $rootScope.$new();
        ItemCollection = jasmine.createSpyObj('ItemCollection', ['someItem']);

        ItemCrtl = $controller('ItemCtrl', {
            $scope: scope,
            ItemCollection: ItemCollection
        });
    });

For Item, the method isSomething should take care of checking if Item is undefined before doing Item.attachedItem

Testing an aync block is tricky. someItem returns a promise. $q an angular service to which can be used create async functions while testing. We need to resolve the deferred object to test the async task.

    var ItemCollection, ItemCrtl, deferedObj;
    beforeEach(inject(function($controller, $rootScope, $q) {
        $scope = $rootScope.$new();
        deferedObj = $q.defer();
        ItemCollection = jasmine.createSpyObj('ItemCollection', ['someItem']);
        ItemCollection.someItem.andReturn(deferedObj.promise);

        ItemCtrl = $controller('ItemCtrl', {
            $scope: scope,
            ItemCollection: ItemCollection
        });
    });

    it('sets page url', function() {
     deferedObj.resolve({ pageUrl: 'http://url', someItems: [1,2,3] });
     scope.$apply();
     expect(ItemCtrl.pageUrl).toEqual('http://url');
    });
Sign up to request clarification or add additional context in comments.

3 Comments

still giving the same error item.pageUrl is not a object at line no. xxx in the controller file
Change the itemCollection to ItemCollection in your code. Otherwise, your code use the actual service reather than a mocked one. @harsh
@harsh Please review the answer and revert if needed
0

you have to use mock Item data in test like this (assuming attachedItem value is boolean)

    var item={attachedItem:true}
    scope.isSomething(item)

Comments

0
$scope.isSomething = function (Item) {
  if(!Item.attachedItem){
        Item.attachedItem=YOUR_MOCK_VALUE;
  }
  return ItemCollection.someItem(Item.attachedItem);
};

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.