I am new to testing. Can't seem to get my spec file to call the mocked version of my service dependency during a test. Instead, it calls the original, which doesnt work because it's an API that only runs on a native device.
Function in service being tested:
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;
}
};
My mock BarcodeScanner service:
export const BarcodeScanner = {
startScan: (options?: ScanOptions): Promise<ScanResult> => Promise.resolve({
hasContent: true,
content: 'mockContent',
format: 'mockFormat'
}),
}
My spec file:
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');
}));
});
Result:
ScannerService > should start scan
Expected undefined to equal 'mockContent'.
This returns false, because it hits the catch error case, due to calling the original, which does not work in the web browser.
How do I make this call the fake spy? Thanks, help appreciated.
Is
BarCodeScanneran injected service? Meaning inside of theScannerService, is it like this:or
I ask because
BarCodeScanneris inPascalCaseand usually injected services are incamelCase.If it's an injected service, what you have is fine and maybe you need to return a value:
If
BarCodeScanneris not an injected service (it is just an import), then unfortunately this is a limitation ofTypeScriptandJasmineand you will have to mock it a different way.You are going to have to create a Wrapper class for BarCodeScanner.
In your service, you will have to do:
Then in your test, since it's not a dependency injection anymore, you will have to do the following:
The above has been taken from here: https://stackoverflow.com/a/62935131/7365461
If none of the above works, if you can output the
error, maybe that can be helpful too.