简体   繁体   English

Angular CLI 单元测试扩展窗口方法

[英]Angular CLI Unit Testing An Extended Window Method

I am trying to write a unit test for an Angular CLI (v6.0.8, with @angular/core v6.0.9) component that calls a method on the window object injected via a service, but I'm running into some issues.我正在尝试为 Angular CLI(v6.0.8,带有@angular/core v6.0.9)组件编写单元测试,该组件调用通过服务注入的 window 对象上的方法,但我遇到了一些问题。

Here is the component: MyComponent这是组件: MyComponent

import { WindowRefService} from '../../services/window-reference/window-reference.service'

export class MyComponent {

  constructor(private windowRef: WindowRefService) {}

  addAnother() {
    if ((this.windowRef.nativeWindow._thirdPartyWindowObject) {
      this.windowRef.nativeWindow._thirdPartyWindowObject.track("toolstart")
    }
  }
}

and here is the service: WindowRefService这是服务: WindowRefService

import { Injectable } from '@angular/core'

export interface ICustomWindow extends Window {
  _thirdPartyWindowObject: {
    track: Function
  }
}

function getWindow (): any {
    return window
}

@Injectable()
export class WindowRefService {
    get nativeWindow (): ICustomWindow {
        return getWindow()
    }
}

This service is a way to extend the Window type to include a third party library introduced into the window object in the page the app is loaded into.此服务是一种扩展Window类型以包含引入到应用程序加载到的页面中的 window 对象中的第三方库的方法。 Not ideal, I know, but it's the use case I was handed.不理想,我知道,但这是我得到的用例。

This is the test I've written for the addAnother method:这是我为addAnother方法编写的测试:

import { async, ComponentFixture, TestBed } from '@angular/core/testing'

import { MyComponent } from './MyComponent'
import { WindowRefService, ICustomWindow } from '../../services/window-reference/window-reference.service'

class WindowServiceMock {
  get nativeWindow (): ICustomWindow {
    return {
      ...window,
      _thirdPartyWindowObject: {
        track: (props: string) => {
          console.log('props', props)
          return true
        }
      }
    }
  }
}

describe('MyComponent', () => {
  let component: MyComponent
  let fixture: ComponentFixture<MyComponent>
  let windowSpy: WindowServiceMock

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ MyComponent ],
    })
    .overrideComponent(MyComponent, {
      set: {
        providers: [
          { provide: WindowRefService, useClass: WindowServiceMock }
        ]
      }
    })
    .compileComponents()
  }))

  beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent)
    component = fixture.componentInstance
    windowSpy = fixture.debugElement.injector.get(WindowRefService) as any
    fixture.detectChanges()
  })

  it('should call the third party scripts', () => {
    let spy = spyOn(windowSpy.nativeWindow._thirdPartyWindowObject, 'track')
    component.addAnother()
    expect(spy).toHaveBeenCalled()
  })
})

This all works perfectly up until the point I would expect the spy for windowSpy.nativeWindow._thirdPartyWindowObject.track to have been called.这一切都很完美,直到我期望windowSpy.nativeWindow._thirdPartyWindowObject.trackspy被调用windowSpy.nativeWindow._thirdPartyWindowObject.track When I check my logs, I can see the toolstart string being passed into the track method inside WindowServiceMock being logged out so the stubbed service is being called.当我检查我的日志,我可以看到toolstart字符串被传递到track内的方法WindowServiceMock被记录了这样的存根服务调用。 However, for some reason, the spy is not.然而,出于某种原因,间谍不是。

I'm sure I'm missing something extremely obvious here, but any help would be appreciated.我确定我在这里遗漏了一些非常明显的东西,但任何帮助将不胜感激。

Thanks!谢谢!

The issue is that the nativeWindow getter is returning a new object every time it is accessed.问题是nativeWindow getter 每次访问时都会返回一个新对象。 So the function you spied on is not the same one that then gets called later.因此,您监视的函数与稍后调用的函数不同。 Updating the mock's getter to always return a reference to the same _thirdPartyWindowObject object, and hence the same child function, as shown below should fix the issue.更新模拟的 getter 以始终返回对相同_thirdPartyWindowObject对象的引用,因此相同的子函数,如下所示应该可以解决问题。 Not sure if there is a better the jasmine way to do this though.不确定是否有更好的茉莉花方式来做到这一点。

const _thirdPartyWindowObject = {
  track: (props: string) => {
    console.log('props', props)
    return true
  }
}

class WindowServiceMock {
  get nativeWindow (): ICustomWindow {
    return {
      ...window,
      _thirdPartyWindowObject
    }
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM