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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.