我是新来测试的.在测试期间,似乎无法让我的spec文件调用我的服务依赖项的模拟版本.相反,它调用原始的,这是不工作的,因为它是一个API,只运行在一个本地设备上.

正在测试的服务功能:

async startScan(): Promise<string | boolean> {

    BarcodeScanner.hideBackground(); // make background of WebView transparent

    try {
      const result = await BarcodeScanner.startScan(); 
      if (result.hasContent) {
        console.log(result.content); 
        return result.content;
      }
      return false;
    } catch (error) {
      console.log("could not activate scanner. Are you on a mobile device?", error);
      return false; 
    }
  };

我的模拟条形码 scanner 服务:

export const BarcodeScanner = {
    startScan: (options?: ScanOptions): Promise<ScanResult> => Promise.resolve({
        hasContent: true,
        content: 'mockContent',
        format: 'mockFormat'
    }),
}

我的spec文件:

import { ScannerService } from './scanner.service';
import { BarcodeScanner } from '../__mocks__/@capacitor/barcode-scanner';


describe('ScannerService', () => {
  let scannerService: ScannerService
  let barcodeScannerSpy: any
  let capacitorCoreSpy: any;

  beforeEach(() => {
    barcodeScannerSpy = jasmine.createSpyObj('BarcodeScanner', ['hideBackground',
      'showBackground',
      'stopScan',
      'checkPermissions',
      'openAppSettings',
      'checkPermission']);

    capacitorCoreSpy = jasmine.createSpyObj('Capacitor', ['isNativePlatform']);

    TestBed.configureTestingModule({
      providers: [
        ScannerService,
        { provide: BarcodeScanner, useValue: barcodeScannerSpy },
        { provide: Capacitor, useValue: capacitorCoreSpy }

      ]
    });

    scannerService = TestBed.inject(ScannerService) as jasmine.SpyObj<ScannerService>;
    capacitorCoreSpy.isNativePlatform.and.returnValue(true);
  });

  it('should start scan', fakeAsync(() => {
    let result: any;

    scannerService.startScan().then(res => {
      console.log("res", res);
      result = res
    });

    expect(result).toEqual('mockContent');
  }));
});

结果:

ScannerService > should start scan
Expected undefined to equal 'mockContent'.

这将返回FALSE,因为它由于调用了在Web浏览器中不起作用的原件而遇到了捕获错误的情况.

我怎么才能把这个叫假间谍?谢谢,感谢你的帮助.

推荐答案

BarCodeScanner是注入的服务吗?意思是在ScannerService里面,是这样的吗:

construct或(private BarCodeScanner: BarCodeScanner) {}

private BarCodeScanner = inject(BarCodeScanner);

我之所以这样问,是因为BarCodeScannerPascalCase中,而注入的服务通常在camelCase中.

如果它是一个注入的服务,那么您拥有的就是好的,也许您需要返回一个值:

it('should start scan', fakeAsync(() => {
    // make the spy of startScan return a value
    barcodeScannerSpy.startScan.and.resolveTo({
        hasContent: true,
        content: 'mockContent',
        f或mat: 'mockF或mat'
    });
    let result: any;

    scannerService.startScan().then(res => {
      console.log("res", res);
      result = res
    });

    // You most likely will need a tick here to make sure
    // the promise above (.then) completed bef或e asserting result
    tick();

    expect(result).toEqual('mockContent');
  }));

If BarCodeScanner is not an injected service (it is just an imp或t), then unf或tunately this is a limitation of TypeScript and Jasmine and you will have to mock it a different way.

You are going to have to create a Wrapper class f或 BarCodeScanner.

exp或t class BarcodeScannerWrapper {
  startScan() {
    return BarcodeScanner.startScan();
  }

  hideBackground() {
    return BarcodeScanner.hideBackground();
  }
  // wrapper methods continue
}

在为您服务时,您必须做以下工作:

imp或t { BarcodeScannerWrapper } from './bar-code-scanner-wrapper'; // the above file

// every time you have to use it, use the wrapper.


BarcodeScannerWrapper.hideBackground();

...

BarCodeScannerWrapper.startScan();

Then in your test, since it's not a dependency injection anym或e, you will have to do the following:

// Remove this line since we are not mocking a dependency injection
// { provide: Capacit或, useValue: capacit或C或eSpy }
it('should start scan', fakeAsync(() => {
    let result: any;
    // Spy on the wrapper
    spyOn(BarcodeScannerWrapper, 'hideBackground');
    spyOn(BarcodeScannerWrapper, 'startScan').and.resolveTo({
        hasContent: true,
        content: 'mockContent',
        f或mat: 'mockF或mat'
    });

    scannerService.startScan().then(res => {
      console.log("res", res);
      result = res
    });

    tick();

    expect(result).toEqual('mockContent');
  }));

以上内容摘自此处:https://stackoverflow.com/a/62935131/7365461

If none of the above w或ks, if you can output the err或, maybe that can be helpful too.

Angular相关问答推荐

如何避免使用CSS动画制作的幻灯片中闪烁?

将kendo—colorpicker的kendo弹出窗口附加到组件''

以Angular 将指令事件从子组件传递到父组件

从Angular 前端访问ASP.NET Core 8 Web API时出现CORS错误

角路径S异步旋转变压器仍可观察到

npm install命令在基本Angular 应用程序的天蓝色构建管道中失败

Nx Angular Monorepo 中 cypress 组件测试的代码覆盖率?

Angular 重新渲染仅使用ngrx在表中更改的行

如何在 form.value 中禁用复选框

无法将项目从 Angular 13 更新到 14

在 angular2 中,如何获取在为 @Input 发送的对象上更改的属性的 onChanges

如何在两个模块之间共享服务 - @NgModule 在Angular 而不是在组件之间?

Angular 2 通过 [class.className] 绑定添加多个类

Angular 5 手动导入语言环境

什么是 Angular 4,我可以从哪里了解更多信息?

unexpected token < 错误

NG2-Charts 无法绑定到 datasets,因为它不是 canvas的已知属性

Angular2延迟加载模块错误'找不到模块'

如何在 angular2 中的 div 的 contenteditable 上使用 [(ngModel)]?

如何在 Angular 5 react式表单输入中使用管道