Search code examples
typescriptjestjses6-module-loader

Jest test suite failed to run because of "TypeError: Cannot read property 'xxx' of undefined"


I am trying to reorganize the import/export statements of my TypeScript React project to make them shorter and cleaner, basically by the approach of defining an index.ts file in each feature specific folder to export resources (interface/type/function etc.) of that feature. This Smarter way to organize "imports" blog explains almost the same idea.

But suddenly jest execution breaks with below stack trace after the changes. The entities involved have been spoofed for confidentiality purpose.

Test suite failed to run

    TypeError: Cannot read property 'FooBarEnum' of undefined



      at Object.FooBarEnum (src/features/Zoo/index.ts:93:23)
      at Object.<anonymous> (src/features/CarPark/CarParkManager.ts:18:4)
      at Object.<anonymous> (src/features/CarPark/index.ts:1:1)
      at Object.<anonymous> (src/features/Zoo/ZooManager.ts:1:1)
      at Object.<anonymous> (src/features/Zoo/index.ts:14:1)
      at Object.<anonymous> (src/features/Rabbit/Rabbit.ts:4:1)
      at Object.<anonymous> (test/features/Rabbit/Rabbit.test.ts:2:1)

Basically there is an enum defined in a constant file which can't be read at all.

I am pretty sure my jest setup is correct because it was executing successfully before this. And I use babel-jest and @babel/preset-typescript to compile.

Appreciate if someone can point me to a path for debugging as the stack trace doesn't really tell much.


Solution

  • Finally I realized this is caused by a hidden circular dependency in my code base.

    [TL;DR] Dependency cycle: Rabbit > Zoo index > CarPark index > Zoo index.

    [Details] The situation is that ZooManager is exported from the index file of Zoo folder, and ZooManager imports CarParkManager which is exported from the index file of CarPark folder. 'FooBarEnum' is exported from the index file of Zoo folder and is used by CarParkManager, and that constitutes the dependency cycle.

    I know the given spoofed example isn't really nice to read upon but this provides a hint that when you encounter similar issues, keep an eye on circular dependencies.

    The import/no-cycle ESLint rule can be added to carry out a static check.

    And the madge developer tool can be used to construct a visual module dependency graph.

    References: