evangalen / ng-improved-testing

Improves AngularJS testing
MIT License
21 stars 4 forks source link

looks like cannot inject $rootScopeMock #2

Closed chaiyilin closed 10 years ago

chaiyilin commented 10 years ago

my testing target: module.factory('httpErrorInterceptor', ['$q', '$rootScope', '$injector', 'popupAlert', function ($q, $rootScope, $injector, popupAlert) {.............. my unit test: inject(function (httpErrorInterceptor, $injectorMock, $rootScopeMock) {... the $injectorMock got injected, but not $rootScopeMock. why?

evangalen commented 10 years ago

A mock (at least at this moment) will only be created when an object has at least 1 "own" function properties. The "$rootScope" object has no "own" function properties, all its functions are instead declared (i.e. $watch etc) are declared on its propertype. If you like you always just inject the "$rootScope" (instead of "$rootScopeMock") and do a spyOn on its method (which are part of its prototype).

Furthermore you most likely only would want to mock out services you created yourself and not the build-in ones from AngularJS. So instead of ".serviceWithMocks" you could either use ".serviceWithMocksExcept" (to exclude the dependencies from being mocked out) or ".serviceWithMocksFor" (to only mock out the specified dependencies).

chaiyilin commented 10 years ago

hi,

thanks a lot for reply. though it is perfectly understandable what you explained, isn't it better we still mock all the dependencies whatever they do/don't have "own" function or they are/aren't build-in? it is more universal and less confusing. i believe people still have a lot of build-in angular stuff injected into their code. it is just more convenient to even mock the build-in stuff. and actually some of the build-ins mock are working fine.

but anyway really appreciate your help and hope you keep going with the ng-improved-testing. the idea is amazing.

regards, yilin

Date: Wed, 30 Jul 2014 06:17:52 -0700 From: notifications@github.com To: ng-improved-testing@noreply.github.com CC: chaiyilin@hotmail.com Subject: Re: [ng-improved-testing] looks like cannot inject $rootScopeMock (#2)

A mock (at least at this moment) will only be created when an object has at least 1 "own" function properties. The "$rootScope" object has no "own" function properties, all its functions are instead declared (i.e. $watch etc) are declared on its propertype.

If you like you always just inject the "$rootScope" (instead of "$rootScopeMock") and do a spyOn on its method (which are part of its prototype).

Furthermore you most likely only would want to mock out services you created yourself and not the build-in ones from AngularJS.

So instead of ".serviceWithMocks" you could either use ".serviceWithMocksExcept" (to exclude the dependencies from being mocked out) or ".serviceWithMocksFor" (to only mock out the specified dependencies).

¡ª Reply to this email directly or view it on GitHub.

evangalen commented 10 years ago

Thanks you very much for your feedback.

Maybe it indeed more consistent to always mock the dependencies (when requested) and not make it dependent on the type (whether is a function / object or not) and structure of the actual service (if an object contains any "own" function properties). Since I wanted mocks to be 100% separate from it's original service instance I decided not to mock a service when it cannot be mocked (using the current mocking algorithm). But maybe I could somehow think of a way to be able to always mock any kind service.

Additionally I would like to introduce a way to configure some default inclusions/ exclusions for mocking dependencies. This way once you centrally configure that you want to exclude all services from the "ng" module from mocking.

evangalen commented 10 years ago

Just modified ngImprovedTesting (for it's upcoming 0.1.2 version) to support creation of mocks for objects with inherited methods (like $rootScope with inherited methods in its prototype).