注入服务更改时,HTML不会在角度测试中更新

时间:2018-05-09 12:11:04

标签: angular unit-testing jasmine

我正在尝试根据当前用户详细信息测试显示或隐藏按钮的组件。我从服务上的方法中获取用户详细信息。该组件使用getter来调用服务方法。

在组件中:

get me() {
  return this.sessionService.getMe()
}

在组件的html中:

<a id="profile-button" *ngIf="me.loggedIn" routerLink="profile">Profile</a>

我需要测试我登录时是否显示该按钮,并且在我未登录时未显示该按钮。我正在按如下方式对会话服务进行存根:

在组件规范文件中:

let sessionServiceStub = {
  currentUser: {
    loggedIn: false
  }

  getMe: function () {
    return this.currentUser
  }
}

beforeEach(async(() => {
  TestBed.configureTestingModule({
    imports: ['RouterTestingModule'],
    declarations: ['MyComponent'],
    providers: [{provide: SessionService, useValue: sessionServiceStub}],
  }).compileComponents()
}))

beforeEach(() => {
  sessionServiceStub.currentUser = {
    loggedIn = false
  }

  fixture = TestBed.createComponent(MyComponent);
  component = fixture.componentInstance;
  fixture.detectChanges();
})

在每次测试开始时,我将服务存根上的loggedOn属性设置为true或false,然后调用detectChanges(),但HTML不会按预期更新。这是与getter有关,如果是这样,我如何强制视图从sessionService获取新值?

在组件规范文件中:

it('shows the button when a user is logged in', () => {
  sessionServiceStub.currentUser.loggedIn = true
  fixture.detectChanges()

  de = fixture.debugElement.query(By.css('#profile-button'))
  el: HTMLAnchorElement = de.nativeElement // TypeError: Cannot read property 'nativeElement' of null
  // ...
})

3 个答案:

答案 0 :(得分:1)

从beforeEach方法中删除fixture.detectChanges()。

beforeEach(() => {
  sessionServiceStub.currentUser = {
    loggedIn = false
  }

  fixture = TestBed.createComponent(MyComponent);
  component = fixture.componentInstance;

})

它应该可以正常工作。

答案 1 :(得分:1)

将sessionsServiceStub添加到providers数组时,会为测试创建一个新实例。在创建实例之后,我正在修改原始存根,并且在下一次测试(创建新实例时)之前这些更改不可用。

通过从存根中删除currentUser,对它进行的任何更改仍将可用于测试,因为新实例将引用相同的currentUser对象。

path

答案 2 :(得分:0)

您可能希望采用以下方法:describe函数可以嵌套在其他describe函数中。这使您可以将测试结构分成几个部分,这些部分将共享共同的锅炉板,如下所示。

警告:以下代码仅供参考,尚未经过测试。

describe('MyComponentUnderTestComponent', () => {
  let component: MyComponentUnderTestComponent
  let fixture: ComponentFixture<MyComponentUnderTestComponent>

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: ['RouterTestingModule'],
      declarations: ['MyComponent'],
      providers: [{provide: SessionService, useValue: sessionServiceStub}],
    }).compileComponents()
  }))

  describe('when user is connected', () => {
    beforeEach(() => {
      sessionServiceStub.currentUser.loggedIn = true
      fixture = TestBed.createComponent(MyComponent)
      component = fixture.componentInstance
      fixture.detectChanges()
    })

    it('shows the button when a user is logged in', () => {
      de = fixture.debugElement.query(By.css('#profile-button'))
      el: HTMLAnchorElement = de.nativeElement
      // ...
    })
  })

  describe('when user is NOT connected', () => {
    beforeEach(() => {
      sessionServiceStub.currentUser.loggedIn = false
      fixture = TestBed.createComponent(MyComponent)
      component = fixture.componentInstance
      fixture.detectChanges()
    })
  })

  it('does NOT show the button when a user is NOT logged in', () => {
    de = fixture.debugElement.query(By.css('#profile-button'))
    el: HTMLAnchorElement = de.nativeElement
    // ...
  })
})

这种方法在第一个站点稍微复杂一点,然后就是你所采用的方法。但是,它有几个好处:

  1. 嵌套describe函数在测试中创建不同的上下文:“用户已登录”vs“用户未登录”。它有助于将锅炉板共享用于共享相同环境的测试。

  2. 因此,它会在您的文件中分隔完全不同的测试用例。

  3. 它使用beforeEach函数来设置上下文(“用户已登录”,“用户未登录”)它应该是it函数,而不是“在运行中”,在public function classWiseResult(Request $request){ $students = Students::where('class',$request->class) ->withCount(['firstTerm as firstTermPromoted' => function($q) { $q->where('number', '>', 32); }]) ->withCount('firstTerm as firstTermAllCount') ->withCount(['secondTerm as secondTermPromoted' => function($q) { $q->where('number', '>', 32); }]) ->withCount('secondTerm as secondTermAllCount') ->withCount(['finalTerm as finalTermPromoted' => function($q) { $q->where('number', '>', 32); }]) ->withCount('finalTerm as finalTermAllCount') ->with('firstTerm') ->with('secondTerm') ->with('finalTerm') ->get(); return view('admin.showResult.show',compact('students')); } 函数中,可能很难找到其他开发人员(即使是从现在开始的几天内自己)。