Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Can't export pipe MockOfAsyncPipe from MockOfPipeModule as it was neither declared nor imported! #4344

Closed
GipHub123 opened this issue Nov 23, 2022 · 21 comments · Fixed by #4350 or #4418
Assignees
Labels

Comments

@GipHub123
Copy link

GipHub123 commented Nov 23, 2022

Description of the bug

Hi,

I've started to migrating a project to use standalone components.
Not sure if this is bug or just me doing something wrong / is there something wrong with my environment?

I was able to create a simple example project.

When I run "ng test" -command, I got consistently following error:


Chrome 107.0.0.0 (Windows 10) NotStandaloneComponent should create FAILED
        Error: Can't export pipe MockOfAsyncPipe from MockOfPipeModule as it was neither declared nor imported!
        Can't export pipe MockOfCurrencyPipe from MockOfPipeModule as it was neither declared nor imported!
        Can't export pipe MockOfDatePipe from MockOfPipeModule as it was neither declared nor imported!
        Can't export pipe MockOfDecimalPipe from MockOfPipeModule as it was neither declared nor imported!
        Can't export pipe MockOfPercentPipe from MockOfPipeModule as it was neither declared nor imported!
            at verifySemanticsOfNgModuleDef (node_modules/@angular/core/fesm2020/core.mjs:24259:15)
            at Function.get (node_modules/@angular/core/fesm2020/core.mjs:24183:21)
            at getInjectorDef (node_modules/@angular/core/fesm2020/core.mjs:485:13)
            at walkProviderTree (node_modules/@angular/core/fesm2020/core.mjs:6479:18)
            at walkProviderTree (node_modules/@angular/core/fesm2020/core.mjs:6520:17)
            at walkProviderTree (node_modules/@angular/core/fesm2020/core.mjs:6520:17)
            at fn (node_modules/@angular/core/fesm2020/core.mjs:6535:25)
            at forEach (node_modules/@angular/core/fesm2020/core.mjs:4217:76)
            at Array.forEach (<anonymous>)
            at deepForEach (node_modules/@angular/core/fesm2020/core.mjs:4217:11)
Chrome 107.0.0.0 (Windows 10): Executed 6 of 6 (1 FAILED) (0.341 secs / 0.307 secs)
TOTAL: 1 FAILED, 5 SUCCESS
$ ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 14.2.10
Node: 16.17.0
Package Manager: npm 8.15.0
OS: win32 x64

Angular: 14.2.11
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, router

Package                         Version
---------------------------------------------------------
@angular-devkit/architect       0.1402.10
@angular-devkit/build-angular   14.2.10
@angular-devkit/core            14.2.10
@angular-devkit/schematics      14.2.10
@angular/cli                    14.2.10
@schematics/angular             14.2.10
rxjs                            7.5.7
typescript                      4.7.4

An example of the bug

Link:
example_v2.zip

Weird thing is that when I run this failing test cases with WebStorm -> It passes consistently.
I tested this also with latest v15 and got similar results.

standalone_webstorm

Expected vs actual behavior

Test passes

@GipHub123 GipHub123 added the bug Something isn't working label Nov 23, 2022
@satanTime
Copy link
Member

satanTime commented Nov 23, 2022

Hi @GipHub123,

thanks for the report.

a single test:

import {TestBed} from '@angular/core/testing';
import {MockComponent, MockRender} from 'ng-mocks';
import {Component,NgModule} from '@angular/core';
import {AsyncPipe, CommonModule} from '@angular/common';

@NgModule({
  imports: [CommonModule],
  exports: [AsyncPipe],
})
export class SharedModule {}

@Component({
  selector: 'standalone',
  standalone: true,
  template: '',
  imports: [SharedModule],
})
export class StandaloneComponent {}

describe('issue-4344', () => {
  describe('step1', () => {
    beforeEach(async () => {
      await TestBed.configureTestingModule({
        imports: [StandaloneComponent],
      }).compileComponents();
    });

    it('creates NotStandaloneComponent', () => {
      expect(() => MockRender(StandaloneComponent)).not.toThrow();
    });
  });

  describe('step2', () => {
    beforeEach(async () => {
      await TestBed.configureTestingModule({
        imports: [MockComponent(StandaloneComponent)],
      }).compileComponents();
    });

    it('creates NotStandaloneComponent', () => {
      expect(() => MockRender(StandaloneComponent)).not.toThrow();
    });
  });
});

@satanTime
Copy link
Member

I found the problem, that's because of cached declarations.

Is there a reason why you don't use MockBuilder?

The min test to reproduce the issue:

import {TestBed} from '@angular/core/testing';
import {MockModule, MockRender} from 'ng-mocks';
import {Component,NgModule} from '@angular/core';
import {AsyncPipe, CommonModule} from '@angular/common';

@Component({
  selector: 'target',
  template: '',
})
export class TargetComponent {}

@NgModule({
  declarations: [TargetComponent],
  imports: [CommonModule],
  exports: [AsyncPipe, TargetComponent],
})
export class TargetModule {}

// @see https://github.com/help-me-mom/ng-mocks/issues/4344
// exporting AsyncPipe from CommonModule which is kept,
// causes an issue, because ng-mocks mocks AsyncPipe, whereas it shouldn't.
// That happens because a previously checked CommonModule doesn't expose its guts anymore.
describe('issue-4344', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [MockModule(CommonModule), MockModule(TargetModule)],
    }).compileComponents();
  });

  it('creates NotStandaloneComponent', () => {
    expect(() => MockRender(TargetComponent)).not.toThrow();
  });
});

@GipHub123
Copy link
Author

GipHub123 commented Nov 23, 2022

Hi. Thanks for fast reply.

I've been using MockBuilder whenever it's needed / I was not able to get test working.
Have encountered a few test cases that I've not been able to fix with using MockBuilder.

Project contains ~2200 test cases so I'm trying to make changes only when it's absolutely needed.

zip-file contained how I've been able to get rid the error (file not-standalone.component-workaround.spec.ts).

MockBuilder is causing some troubles because I didn't find a way to pass extra module / functionality.
In another way API seemed to suitable only to mock / replace / keep that component actual imports. Or just didn't get it right :)

Have been trying to achieve following.

await TestBed.configureTestingModule({
imports: [
        ExtraModuleThatIsNotImportedByTestComponent,
        TestComponent
      ]
    }).compileComponents();

Most component's in a project are using ngx-translate so I've been using that extra module to set translation test context so that I can verify that translations are actually working.

@satanTime
Copy link
Member

Understood, thanks for the info.

A fix should released soon.

satanTime added a commit to satanTime/ng-mocks that referenced this issue Nov 26, 2022
satanTime added a commit that referenced this issue Nov 26, 2022
fix(core): correct caching of touched declarations #4344
@satanTime
Copy link
Member

v14.4.0 has been released and contains a fix for the issue. Feel free to reopen the issue or to submit a new one if you meet any problems.

@GipHub123
Copy link
Author

I've no longer the same problems / I can verify bug fix works.
Thanks for the quick fix

@satanTime
Copy link
Member

Hey there, thanks for the feedback.

Feel free to report anything what you stumble over with the lib or angular testing.

Stay in touch.

@GipHub123
Copy link
Author

@satanTime

Hi. I continued the migration and stumble across same kind of problem.

WebStorm successfully runs the test case but using ng test -> test fails.
Here error comes (MatRippleModule) from a mocked component.
Tested component doesn't have any Mat* -modules directly imported or use them in a HTML -template.

webstorm

  QueryGroupViewComponent
    init
      × button options
        Chrome Headless 107.0.5304.121 (Windows 10)
      Error: Type MatRipple is part of the declarations of 2 modules: MatRippleModule and MockOfMatRippleModule! Please consider moving MatRipple to a higher module that imports MatRippleModule and MockOfMatRippleModule. You can also create a new NgModule that exports and includes MatRipple then import that NgModule in MatRippleModule and MockOfMatRippleModule.
          at verifySemanticsOfNgModuleDef (node_modules/@angular/core/fesm2020/core.mjs:24259:15)
          at forEach (node_modules/@angular/core/fesm2020/core.mjs:24232:9)
          at Array.forEach (<anonymous>)
          at verifySemanticsOfNgModuleDef (node_modules/@angular/core/fesm2020/core.mjs:24230:60)
          at forEach (node_modules/@angular/core/fesm2020/core.mjs:24232:9)
          at Array.forEach (<anonymous>)
          at verifySemanticsOfNgModuleDef (node_modules/@angular/core/fesm2020/core.mjs:24230:60)
          at Function.get (node_modules/@angular/core/fesm2020/core.mjs:24183:21)
          at getInjectorDef (node_modules/@angular/core/fesm2020/core.mjs:485:13)
          at walkProviderTree (node_modules/@angular/core/fesm2020/core.mjs:6479:18)

I tried to reopen this issue but it looked that I don't have necessary rights to do it :|

@satanTime satanTime reopened this Nov 29, 2022
@satanTime
Copy link
Member

Hi @GipHub123, could you share a min example of the failing project?

@GipHub123
Copy link
Author

@satanTime.
Sure. I'll try to create a simple test case for you.

@GipHub123
Copy link
Author

I tried to make simplified test case for you but unfortunately I haven't been able to reproduce the bug 😢

@satanTime
Copy link
Member

Hey there.

I think it's a combination of two tests, there the first one breaks the second one.

I would suggest to delete a test by test in your project, and if the project stops to fail - restore the deleted one and continue deletion of others until you have 2 or 3 tests left.

That should be enough to create a min project with the issue.

@GipHub123
Copy link
Author

I updated project to the V15 since all 3rd parties had added support for v15.

$ ng version

     _                      _                 ____ _     ___
    / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
   / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
  / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
 /_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
                |___/


Angular CLI: 15.0.1
Node: 16.17.0
Package Manager: npm 8.15.0
OS: win32 x64

Angular: 15.0.1
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... platform-server, router

Package                                    Version
--------------------------------------------------------------------
@angular-devkit/architect                  0.1500.1
@angular-devkit/build-angular              15.0.1
@angular-devkit/core                       15.0.1
@angular-devkit/schematics                 15.0.1
@angular/cdk                               15.0.0
@angular/google-maps                       15.0.0
@angular/material                          15.0.0
@angular/material-date-fns-adapter         15.0.0
@nguniversal/builders                      15.0.0
@nguniversal/common                        15.0.0
@nguniversal/express-engine                15.0.0
@nguniversal/module-map-ngfactory-loader   v8.2.6
@schematics/angular                        15.0.1
rxjs                                       7.5.7
typescript                                 4.8.4

Same problem exists here.
Type CdkFixedSizeVirtualScroll is part of the declarations of 2 modules: MockOfScrollingModule and ScrollingModule! Please consider moving CdkFixedSizeVirtualScroll to a higher module that imports MockOfScrollingModule and ScrollingModule.

Project is quite complicated.
I tried similar deduction method and realized that it'll take a lot of time / it's not worth doing. I'll try to figure something out :)

@satanTime
Copy link
Member

But if you remove the failing test - does it work or fails on a different test?

@GipHub123
Copy link
Author

I managed to get pass this. When I deleted most of the my test cases.

  1. ng test -command failed with compilation error.
  2. ng serve -command compiled the code without any errors.

I rolled back most the changes and restarted migration.
Still not sure what caused it but my best bet is some kind of weird circular dependency issue.
All barrel files / import statements looked pretty solid to me.

With these comment, I'll close this issue as completed.

@satanTime
Copy link
Member

Hi @GipHub123,

I would say based on:

Type CdkFixedSizeVirtualScroll is part of the declarations of 2 modules: MockOfScrollingModule and ScrollingModule! Please consider moving CdkFixedSizeVirtualScroll to a higher module that imports MockOfScrollingModule and ScrollingModule.

one of your tests imports ScrollingModule, and the problem is that 2 modules / standalone components import it, where one is mocked and another one is kept, so as the result the creation of MockOfScrollingModule in one if them which mocks CdkFixedSizeVirtualScroll, which exists as it is in the kept part with ScrollingModule.

Could you share the beforeEach of this test?

@satanTime
Copy link
Member

Could you check if you test looks like that one?

import {CdkFixedSizeVirtualScroll, ScrollingModule } from "@angular/cdk/scrolling";
import {Component, NgModule} from "@angular/core";
import {TestBed} from "@angular/core/testing";
import {MockModule, MockRender, ngMocks} from "ng-mocks";

@Component({
  selector: 'dependency',
  template: '<cdk-virtual-scroll-viewport [itemSize]="15"></cdk-virtual-scroll-viewport>',
})
class DependencyComponent {}

@NgModule({
  imports: [ScrollingModule],
  declarations: [DependencyComponent],
  exports: [DependencyComponent, ScrollingModule],
})
class DependencyModule {}

@Component({
  selector: 'target',
  template: '<dependency></dependency><cdk-virtual-scroll-viewport [itemSize]="15"></cdk-virtual-scroll-viewport>',
})
class TargetComponent {}

@NgModule({
  imports: [DependencyModule],
  declarations: [TargetComponent],
  exports: [TargetComponent],
})
class TargetModule {}

ngMocks.globalKeep(CdkFixedSizeVirtualScroll);

// @see https://github.com/help-me-mom/ng-mocks/issues/4344
// Type CdkFixedSizeVirtualScroll is part of the declarations of 2 modules:
// MockOfScrollingModule and ScrollingModule!
// Please consider moving CdkFixedSizeVirtualScroll to a higher module
// that imports MockOfScrollingModule and ScrollingModule.
fdescribe('issue-4344', () => {
  describe('fully mocked', () => {
    beforeEach(() => TestBed.configureTestingModule({
      imports: [
        MockModule(DependencyModule),
        TargetModule,
      ],
    }).compileComponents());

    it('creates TargetComponent', () => {
      expect(() => MockRender(TargetComponent)).not.toThrow();
    });
  });
});

where you keep a declaration globally with ngMocks.globalKeep, or your test mocks and imports modules with the same shared module?

@satanTime
Copy link
Member

Hi @GipHub123,

could you check whether this build fixes the issue: ng-mocks.zip?

@satanTime satanTime reopened this Dec 3, 2022
@GipHub123
Copy link
Author

Hi,

Not really 😐

I haven't use ngMocks.globalKeep -statement in any test case.

Those MockOfScrollingModule and MatRippleModule errors came somewhere really deep from the component/module structure. I mean really really deep 😳
Code should have never reach there because all components / providers where mocked in a test case.

As I said earlier I haven't encounter these errors anymore 👍
I haven't change the way I set up the test cases / how I use ng-mocks.

I used quite a mount of time to investigate this one with no luck.
I would suggest to reopen this issue if somebody else has similar problems 😊

@satanTime
Copy link
Member

I see, that's good :)

if you have a chance to setup the failing env and test the updated build, it'll be really great.

Otherwise, stay in touch and have a nice weekend!

satanTime added a commit to satanTime/ng-mocks that referenced this issue Dec 4, 2022
satanTime added a commit to satanTime/ng-mocks that referenced this issue Dec 10, 2022
satanTime added a commit to satanTime/ng-mocks that referenced this issue Dec 11, 2022
satanTime added a commit that referenced this issue Dec 11, 2022
feat(core): hidden usage of MockBuilder in TestBed if kept and mock modules are used together #4344
@satanTime
Copy link
Member

v14.5.0 has been released and contains a fix for the issue. Feel free to reopen the issue or to submit a new one if you meet any problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment