angularunit-testingtypescriptdependency-injectionangular2-di

How to inject helper class dynamically


I have a component that uses one of two helper classes, like:

import {HelperA} ...
import {HelperB} ...
...

@Component({..})
export class MyComponent implements OnInit {
    helper: Helper;     
    constructor(private ref: ElementRef, private device: MyDeviceDetectionService) {}

    ngOnInit() {
        if (this.device.isMobile) {
            this.helper = new HelperA(this.ref);
        } else {
            this.helper = new HelperB(this.ref);
        }
    }
}

I realise that this is hard to unit test, so how can I inject these? Ideally I only need one of them, depending on whether isMobile is true or false.


Solution

  • It's possible you can push all of that out to the injector. Assuming the two helpers have a common superclass named Helper, use the useFactory provider option to create whichever you need:

    providers: [
      ...,
      { provide: Helper, useFactory: createHelper, deps: [MyDeviceDetectionService, ElementRef] },
    ]
    

    Then the factory would look like:

    export function createHelper(device: MyDeviceDetectionService, ref: ElementRef): Helper {
      if (device.isMobile) {
        return new HelperA(ref);
      } else {
        return new HelperB(ref);
      }
    }
    

    Note that this will have to be in the component's providers array, as the element reference isn't available at the module level.