Angular Web Framework Services & Dependency Injection 4 — Questions and Answers
Question 1: What does `providedIn: 'any'` do in Angular's @Injectable decorator?
- Registers a single global singleton in the root injector
- Creates a separate singleton instance for each lazy-loaded module that injects it (Correct answer)
- Makes the service available only in eagerly loaded modules
- Provides the service in every component injector automatically
Correct answer: Creates a separate singleton instance for each lazy-loaded module that injects it
providedIn: 'any' gives each lazy-loaded module its own singleton while all eagerly loaded code shares one instance.
Question 2: In Angular's hierarchical injection system, what happens when an injector cannot find a requested token?
- It returns undefined immediately
- It throws a NullInjectorError (Correct answer)
- It creates an empty placeholder service
- It falls back to the platform injector automatically
Correct answer: It throws a NullInjectorError
When no injector in the hierarchy can satisfy a token and no @Optional() is present, Angular throws a NullInjectorError.
Question 3: Which Angular injector level sits above the root (AppModule) injector?
- Environment injector
- Module injector
- Platform injector (Correct answer)
- Element injector
Correct answer: Platform injector
The platform injector is created by platformBrowserDynamic() and sits above the root injector; it holds platform-wide services shared across multiple Angular apps on the same page.
Question 4: What is the purpose of `@SkipSelf()` in Angular dependency injection?
- Skips the service's constructor and returns an empty instance
- Tells Angular to start the injector lookup from the parent injector, bypassing the current one (Correct answer)
- Marks the dependency as not required in the current module
- Prevents the service from being included in the production bundle
Correct answer: Tells Angular to start the injector lookup from the parent injector, bypassing the current one
@SkipSelf() causes Angular to skip the current element's injector and search up the tree starting from the parent, preventing circular use of the current injector.
Question 5: How does Angular's `forRoot()` pattern prevent duplicate service instances in feature modules?
- It automatically tree-shakes extra service registrations
- It provides services in the module's forRoot() call so only the root import registers them (Correct answer)
- It uses useExisting to alias all feature module services to the root instance
- It marks services as singletons via a special decorator
Correct answer: It provides services in the module's forRoot() call so only the root import registers them
The forRoot() convention puts service providers in the return value of the static forRoot() method, which is called only once in AppModule, ensuring a single instance.
Question 6: Which Angular testing utility configures providers for dependency injection in unit tests?
- TestBed.inject()
- TestBed.configureTestingModule() (Correct answer)
- TestBed.overrideProvider()
- TestBed.createComponent()
Correct answer: TestBed.configureTestingModule()
TestBed.configureTestingModule() sets up the testing module, including the providers array where you register real or mock services.
Question 7: What Angular API retrieves a service instance from the current injector inside a component class?
- this.injector.resolve(ServiceClass)
- Injector.create().get(ServiceClass)
- inject(ServiceClass) called in an injection context (Correct answer)
- this.providers.get(ServiceClass)
Correct answer: inject(ServiceClass) called in an injection context
The inject() function, when called inside a constructor or field initializer (an injection context), retrieves the service from the active injector.
What does `providedIn: 'any'` do in Angular's @Injectable decorator?