1

How do I list all the dependency injectors of a component in angular?

This requirement is for unit testing.

I have an instance of a component created as follows :

component = fixture.componentInstance();

So in my test case, I need something like

console.log(component.constructor.params) // should print all the constructor parameteres

For ex in the below code :

constructor(private _logger: LoggerService, private _router: Router,
                private _adminService: AdminService) {
}

I need to fetch array of DI's

0 -> LoggerService
1 -> Router
2 -> AdminService
3
  • by testing what you refer to? Karma testing? add these into TestBed providers array? Commented Jun 18, 2018 at 14:48
  • Yes, karma-jasmine testing. Basically I want to check if the component injects particular service or not. Commented Jun 18, 2018 at 14:50
  • 5
    You should be testing behavior, not implementation, IMHO. Commented Jun 18, 2018 at 15:02

3 Answers 3

0

You should be able to take advantage of Javascript's built in arguments object.

So if you just need the names of the classes of each dependency, you can put this in your constructor:

constructor(
    private _logger: LoggerService, 
    private _router: Router,
    private _adminService: AdminService
) {
    let dependencies = Array.from(arguments).map((item) => item.constructor.name);
}

Logging the dependencies object to the console should output:

0: "LoggerService"
1: "Router"
2: "AdminService"

If your array needs to contain the full object instead of the name of the class, just remove the .map() function from the constructor code.

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

6 Comments

But how do I do that outside of constructor function?
@AmitChigadani you can just declare a property called dependencies in the class itself: dependencies = any[]; then in the constructor, set this.dependencies = instead of let dependencies =. Then you can always refer to this.dependencies whenever you need access to the array.
Sorry, but I don't want to make any changes to my existing code. Also In that case, I could directly add this line in my component file like this.dependencies = ['LoggerService', 'Router', 'AdminService']; because I know what are my DI's in my constructor.
Then you're going to need an instance of your class and iterate over all of the keys of this instance, to check if thos keys are instances of a specific class with either instanceof or constructor.name.
@AmitChigadani then I'm unclear what you're trying to accomplish. In your question you say, "in the below code I need to fetch array of DI's". I gave you a way to fetch the DI's in the constructor, so what else do you need? If you don't want to change your code then there is no way to access the injections from outside the class, since they are private (at least from a TypeScript point of view). trichetriche is right, you'd have to manually enumerate over the keys, and that would only work when you know exactly what you're looking for.
|
0

You could monkey patch your constructor before the dependency injection:

function keepConstructorDependenciesOf(MyClass) {
  // keep references to your class and your constructor
  const originalPrototype = MyClass.prototype;
  const originalConstructor = MyClass;

  // add the logic to retrieve the type of dependencies 
  MyClass = function() { 
    this.dependencies = Array.from(arguments).map(a => a.constructor.name); 
    originalConstructor.apply(this, arguments)  
  }

  // re-apply the original prototype
  MyClass.prototype = originalPrototype;

  return MyClass;
}

Component = keepConstructorDependenciesOf(Component);

// run the dependency injection
...

component = fixture.componentInstance();

expect(component.dependencies).toEqual([
  'LoggerService', 
  'Router', 
  'AdminService'
])

Some references about redefining a constuctor

Comments

-1

Use this code to print out the constructor parameter. where you have to Provider to mention the services and router.

//import module services and router her 


 describe('MyComponent', () => {
  let _logger: LoggerService;
  let _router : Router;
  let _adminService :AdminService;
beforeEach(async(() => {

  TestBed.configureTestingModule({
    declarations: [
        MyComponent,
    ],
    imports: [ 
        CommonModule,
        FormsModule,
        HttpModule
  ],
  providers: [

  {provide:AdminService,  useValue: adminService},     
  {provide:Router, useValue:routerSpy} ,     
  {provide:LoggerService, useValue: logService } ,     

  ],
  }).compileComponents();

  fixture = TestBed.createComponent(MyComponent);
 component = fixture.componentInstance;
 _adminService = new AdminService(http);
  _logger = new LoggerService(http); 
}));  
    it('should create the app', async(() => {
      const fixture = TestBed.createComponent(MyComponent);
      component = fixture.componentInstance;
      const app = fixture.debugElement.componentInstance;
     console.log(component.constructor); 
    // should print all the constructor parameteres 
      expect(app).toBeTruthy();
    }));
}));

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.