Barrel Import Appears To Break Load Order

我与影子孤独终老i 提交于 2019-12-20 02:57:07

问题


I've got a component that I'm trying to unit test but I keep getting these errors, depending on my import statements:

Error: Cannot resolve all parameters for 'MyComponent'(undefined, FormBuilder).

TypeError: Cannot read property 'toString' of undefined

My component takes 2 parameters, one the FormBuilder and one a custom service, that must be injected:

import {MyService} from '../';

@Component({
    ...,
    providers: [MyService]
})
class MyComponent {
    constructor(service: MyService, fb: FormBuilder) { ... }
    ...
}

And my unit test is setup as follows:

import {MyComponent} from './';
import {MyService} from '../';

describe('Component: MyComponent', () => {

    let builder: TestComponentBuilder;

    beforeEachProviders(() => [
        MyService,
        MyComponent
    ]);

    beforeEach(inject([TestComponentBuilder], function (tcb: TestComponentBuilder) {
        builder = tcb;
    }));

    it('should inject the component', inject([MyComponent],      
        (component: MyComponent) => {
            expect(component).toBeTruthy();
        })
    );

}

The imports seem to be the problem, since I'm trying to use barrels:

|
|- my-component
|  |- index.ts
|  |- my.component.ts
|  |- my.component.spec.ts
|
|- my-service
|  |- index.ts
|  |- my.service.ts
|
|- index.ts

Inside my index.ts files, I'm doing:

export * from '<filename>';
export * from '<directory>';

as appropriate.

However, when I change the imports in the unit test AND component to reference the service file directly, the unit test works.

import {MyService} from '../my-service/my.service';

I'm using angular-cli in this project and SystemJS is being configured with the generated config file from that:

...
const barrels: string[] = [
  ...,

  // App specific barrels.
  'app',
  'app/my-service',
  'app/my-component'
  /** @cli-barrel */
];

const cliSystemConfigPackages: any = {};
barrels.forEach((barrelName: string) => {
  cliSystemConfigPackages[barrelName] = { main: 'index' };
});

/** Type declaration for ambient System. */
declare var System: any;

// Apply the CLI SystemJS configuration.
System.config({
  map: {
    '@angular': 'vendor/@angular',
    'rxjs': 'vendor/rxjs',
    'main': 'main.js'
  },
  packages: cliSystemConfigPackages
});
...

It seems that when I import from the barrels, the component and service definitions aren't loaded ahead of the unit test code. The application itself will transpile and run, either way.

Sorry if this is asking a broad question, but I'm still pretty new to barrels and SystemJS and I don't know how to narrow the scope further:

Is this a bug with SystemJS/Jasmine/TypeScript/Angular2 or am I doing something wrong in my setup?


回答1:


I'd have to see the contents of the barrels you're importing from to know for sure but it sounds like you need to change the ordering of exports within your barrel.

An issue in the angular2 repo exists here: https://github.com/angular/angular/issues/9334

If a component (A) imports and uses a service/component (B) from a barrel containing the exports of both A and B, and A appears before B in the barrel, the imported value of B is undefined.

So in your case, if you modify your root index.ts to the following, you should be able to import from your barrels.

export * from my-service;
export * from my-component;


来源:https://stackoverflow.com/questions/37398829/barrel-import-appears-to-break-load-order

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!