代码之家  ›  专栏  ›  技术社区  ›  Korr

如何用Jest模拟组件测试中服务的功能

  •  0
  • Korr  · 技术社区  · 3 年前

    我很难用玩笑来测试角度分量。

    我有一个组件:

    媒体形象。组成部分ts

    import { Component, Input } from '@angular/core'
    import { SanityService } from '@services/sanity/sanity.service'
    import Waypoint from '@interfaces/waypoint'
    
    @Component({
      selector: 'app-media-image',
      templateUrl: './media-image.component.html',
      styleUrls: ['./media-image.component.scss']
    })
    export class MediaImageComponent {
      @Input() mediaData: Waypoint = null
    
      constructor(private _sanity: SanityService) {}
    
      imageUrl(source: any) {
        return this._sanity.urlFor(source)
      }
    }
    

    在模板中调用imageUrl

    此组件需要SanityService

    神志正常服务ts

    import { Injectable } from '@angular/core'
    import { environment } from '@environments/environment'
    import imageUrlBuilder from '@sanity/image-url'
    import sanityClient from '@sanity/client'
    
    @Injectable({
      providedIn: 'root'
    })
    export class SanityService {
      sanityClientCredentials = {
        option: sanityClient({
          projectId: environment.sanity.projectId,
          dataset: environment.sanity.dataset,
          apiVersion: environment.sanity.apiVersion
        })
      }
    
      urlFor(source: any) {
        return imageUrlBuilder(this.sanityClientCredentials.option).image(source).url()
      }
    
    
    }
    

    我想嘲笑 urlFor 服务的函数,只是检查是否使用正确的参数调用它。

    以下是我的尝试:

    import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing'
    import { IonicModule } from '@ionic/angular'
    import { MediaImageComponent } from './media-image.component'
    import { SanityService } from '../../../services/sanity/sanity.service'
    
    import { waypointImage } from '../../../mocks/waypoint.mocks'
    
      beforeEach(
        waitForAsync(() => {
          TestBed.configureTestingModule({
            declarations: [MediaImageComponent],
            providers: [{ provide: SanityService }],
            imports: [IonicModule.forRoot()]
          }).compileComponents()
    
          fixture = TestBed.createComponent(MediaImageComponent)
          component = fixture.componentInstance
          component.mediaData = waypointImage
          fixture.detectChanges()
        })
      )
    
      it('should create', () => {
        // First
        jest.mock('../../../services/sanity/sanity.service', () => {
          return {
           urlFor: jest.fn()
          }
        })
       
       // Second
       const mockSanityService = SanityService as jest.Mock<SanityService> // to avoid typescript alerts
       const mockService = jest
          .spyOn(mockSanityService.prototype, 'urlFor')
          .mockImplementation((source) => {return 'test'})
        })
    
        expect(mockService).toHaveBeenCalled()
        expect(component.imageUrl).toHaveBeenCalled()
        expect(component).toBeTruthy()
      })
    })
    
    

    看来我的嘲笑被忽视了。我总是从电话里听到一个错误 @sanity/image-url 等待特定数据的包。

    我做错了什么?我不明白什么?

    谢谢你的帮助!

    0 回复  |  直到 3 年前
        1
  •  0
  •   Benny Halperin    3 年前

    我不确定这是否会有帮助,但当我需要模拟服务时,我在Jest测试中所做的是:

    jest.mock('...../myService');
    
    describe('...', () => {
        let myServiceMock: MyService;
        ...
    
        beforeEach(() => {
            myServiceMock = TestBed.inject(myServiceMock);
            ...
    
            jest.spyOn(myServiceMock, 'someServiceMethod').mock...
        });
    });
    
        2
  •  0
  •   Korr    3 年前

    多亏了这篇文章,终于找到了实现这一目标的方法: Testing Angular Component using JEST

    以下是我的测试:

    import { ComponentFixture, TestBed } from '@angular/core/testing'
    import { IonicModule } from '@ionic/angular'
    import { MediaImageComponent } from './media-image.component'
    import { SanityService } from '../../../services/sanity/sanity.service'
    
    import { waypointImage } from '../../../mocks/waypoint.mocks'
    
    const mockSanityService = {
      urlFor: jest.fn()
    }
    
    describe('MediaImageComponent', () => {
      let component: MediaImageComponent
      let fixture: ComponentFixture<MediaImageComponent>
      let spy
      beforeEach(
        waitForAsync(() => {
          TestBed.configureTestingModule({
            declarations: [MediaImageComponent],
            providers: [{ provide: SanityService, useValue: mockSanityService }],
            imports: [IonicModule.forRoot()]
          }).compileComponents()
    
          fixture = TestBed.createComponent(MediaImageComponent)
          component = fixture.componentInstance
          component.mediaData = waypointImage
          spy = jest.spyOn(component, 'imageUrl')
          fixture.detectChanges()
        })
      )
    
      afterEach(() => {
        if (fixture) {
          fixture.destroy()
        }
        mockSanityService.urlFor.mockReset()
        spy.mockClear()
      })
    
      it('should create', () => {
        mockSanityService.urlFor.mockImplementationOnce(() => 'plop')
    
        expect(mockSanityService.urlFor).toHaveBeenCalled()
        expect(spy).toHaveBeenCalled()
        expect(component).toBeTruthy()
      })
    })
    

    我希望它对其他人有用:)