【问题标题】:Variables defined in describe is "undefined" in outer functions in angular test (jest/jasmine)描述中定义的变量在角度测试的外部函数中是“未定义的”(jest/jasmine)
【发布时间】:2021-08-07 19:51:25
【问题描述】:

我有这样的代码:

// imports
    
describe('AdminGetRightsComponent', () => {
    
  // Declare variables to be re-initialized before each test suite
  let fixture: ComponentFixture<AdminGetRightsComponent>;
  let component: AdminGetRightsComponent;
  let router: Router;
  let location: Location;
  let debugElement: DebugElement;


  window.alert = jest.fn();

  // Create service stubs
  let nxDialogServiceStub: Partial<NxDialogService>;
  nxDialogServiceStub = {};

  let ServicesRmAdminServiceStub: Partial<ServicesRmAdminService>;
  ServicesRmAdminServiceStub = {

    // Simulate API call, wait for 1000 milliseconds
    async getRights(contactIds: string[]) {
      await new Promise(resolve => setTimeout(resolve, 0));
      return {
        body: TEST_API_RESPONES_BODY
      }
    }
  };

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      declarations: [ AdminGetRightsComponent ],
      imports: [
        RouterTestingModule.withRoutes([{ path: '', component: AdminGetRightsComponent }]),
        HttpClientTestingModule,
        BrowserAnimationsModule,
        modulesForTests
      ],
      providers: [
        { provide: NxDialogService },
        { provide: ServicesRmAdminService, useValue : ServicesRmAdminServiceStub},
        { provide: ServicesFileManagementService }
      ]
    })
    .compileComponents();
  });


  beforeEach(() => {
    router = TestBed.inject(Router);
    location = TestBed.inject(Location);
    fixture = TestBed.createComponent(AdminGetRightsComponent);
    component = fixture.componentInstance;
    component.downloadCSV = jest.fn(() => {
      component.fileUploaderComponent.removeFile(component.files[0]);
    });
    debugElement = fixture.debugElement;
    fixture.ngZone.run(() => {
      router.initialNavigation();
    });
    fixture.detectChanges();
  });


  describe('When uploaded a file', () => {


    beforeEach((done) => {
      fixture.detectChanges();
      uploadFileToComponent(component);
      setTimeout(done, TEST_DEFAULT_TIMEOUT);
    });

    afterEach((done) => {
      fixture.detectChanges();
      // Remove the file
      component.files.length > 0 && component.fileUploaderComponent.fileDeleted.emit(component.files[0]);

      setTimeout(done, TEST_DEFAULT_TIMEOUT);
    });

    it('should have the right UI elements', () => {

      fixture.detectChanges();

      expect(...).toBe(...);
    });

    describe('When clicked on the delete file button', () => {


      beforeEach((done) => {
        fixture.detectChanges();
        getNativeElement('nx-file-upload-delete button', debugElement).click();
        setTimeout(done, TEST_DEFAULT_TIMEOUT);
      });

      it('should remove the right UI elements', () => {
        fixture.detectChanges();
        expect(...).toBe(...);
      });

    });

    // other code

  });

});

在我的代码中,我有很多这样的beforeEach(至少 8 或 9 个位置):

beforeEach((done) => {
  fixture.detectChanges();
  getNativeElement('nx-file-upload-delete button', debugElement).click();
  setTimeout(done, TEST_DEFAULT_TIMEOUT);
});

fixture.detectChanges()setTimeout(...) 是重复的代码,我不想要它。


一开始我是这样写的:

function _beforeEach(callback) {
  eval('fixture.detectChanges()');
  beforeEach((done) => {
    callback();
    setTimeout(done, TEST_DEFAULT_TIMEOUT);
  })
}

然后我用这个_beforeEach 替换了所有以前的beforeEach,这可以帮助我减少每次调用的2 行代码。但上面写着ReferenceError: fixture is not defined


然后我尝试了这样的事情:

function _beforeEach(
  callback,
  fixture: ComponentFixture<AdminGetRightsComponent>
) {
  fixture.detectChanges();
  beforeEach((done) => {
    callback();
    setTimeout(done, TEST_DEFAULT_TIMEOUT);
  });
}

我用上面的_beforeEach 替换了所有以前的beforeEach,当我使用ng test 启动测试时,我收到了错误TypeError: Cannot read property 'detectChanges' of undefined


有人知道为什么会这样吗?

【问题讨论】:

  • 我不明白为什么您会期望 不会 发生,这就是 JavaScript 作用域的工作原理。

标签: angular jestjs jasmine


【解决方案1】:

我想你尝试存档这个:

function _beforeEach(
  callback
) {
  fixture.detectChanges();
  beforeEach((done) => {
    callback();
    setTimeout(done, TEST_DEFAULT_TIMEOUT);
  });
}

虽然我认为不需要fixture.detectChanges();。似乎只是从根 beforeEach 复制相同的代码。

我也会避免setTimeout(done, TEST_DEFAULT_TIMEOUT); 会减慢测试运行的执行时间。在大多数情况下,await fixture.whenStable() 解决了等待异步操作完成的问题。如果还不够,那么fakeAsyncctickjasmine.clock 可能是一个解决方案。虽然它并不总是有效,但我也偶尔放弃并使用超时解决方案。

【讨论】:

  • 感谢await fixture.whenStable(),真的很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-01
  • 2018-05-04
  • 2019-09-11
  • 1970-01-01
  • 2022-06-30
  • 1970-01-01
  • 2019-12-04
相关资源
最近更新 更多