angularunit-testingjasmineinjectangular14

How to unit test a function that uses the new Angular 14's "inject" function?


I've created a function that utilizes that new Angular 'inject' function. Since the inject function can be used only when initializing a class (or factory) that is part of the dependency injection tree, this function is meant to be used in the constructor of a component / service.

I want to unit test this function with mock dependencies. The problem is I can't just call it in unit tests, because it will be called in an incorrect context. I can create a component / service just for the unit test purposes but it feels like too much boilerplate to test a simple function.

Is there a recommended way of doing this?


Solution

  • I know it's been a while, but I finally thought of a solution that is elegant enough to be the standard way of doing it.

    Let's assume the function you want to test is myInjectionFunction:

    // This is a utility function you can put in a shared place and use it whenever you want
    function useInjectionFunction<GArgs extends any[], GReturn>(injectionFunction: (...args: GArgs) => GReturn, injector: Injector) {
      const token = new InjectionToken<GReturn>(injectionFunction.name);
      return (...args: GArgs) => Injector.create({
        parent: injector,
        providers: [
          {
            provide: token,
            useFactory: () => {
              return injectionFunction(...args);
            },
          },
        ],
      }).get(token)
    }
    
    describe('My Test suite', () => {
      let myFunction: typeof myInjectionFunction;
    
      beforeEach(() => {
        TestBed.configureTestingModule({
          // configure your providers here
        });
    
        myFunction = useInjectionFunction(hasFeatureFlag, TestBed.get(Injector));
      });
    
      it('should work', () => {
        // call "myFunction" regularly to test it
      });
    });
    
    

    Leaving it here if anyone wants to use it.