4

I've had trouble spying on exported function in a NodeJS (v9.6.1) app using Jasmine.

The app is written in typescript, transpiled with tsc in a dist folder to be executed as javascript.

App

I have a Foo utils file (foo.utils.ts) which exports functions:

import {readFile} from "fs";
export function getData(filePath: string){
    const data = readFile(filePath)
    // various checks happens here.
    return data;
}

And a Bar class in a bar.ts file:

import {getData} from "../utils/foo.utils
export class Bar {
        public do(){
    // ... does stuff
    const data = getData(filePath);
    // etc.
    }
}

Test

Now I'm trying to spyOn the exported getData method to check if it've been called and to return a mocked value. I don't want to read file in my unit test (and even to use the real getData method at all)

The bar.spec.ts file for testing:

describe("Bar", ()=>{
    let bar: Bar;
    beforeEach(function() {
        bar = new Bar();
    })
    it(" should do stuff", ()=>{
        const spy = spyOn(???, "getData").and.returnValue([]);
        bar.do();
        expect(spy).toHaveBeenCalled();
    })
});

Problems

As it is a NodeJS app, I've been trying to use global as the object to spy on, but I get the error:

Error: : getAttachementData() method does not exist

I've also tried to add

import * as fooutils from ".../src/utils/foo.utils

And spy on fooutils but I still goes through the exported function (and crashes when it tries to read the file...)

Now I'm kinda lost. From what I've found it's not really possible to mock an exported function (even though they should be added to the global object). I thought about refactoring the utils file to create an utils class which exports static method and spying on them.

Questions

  • Am I doing something wrong ?
  • Is it possible to spy (and replace) exported function ?
  • Would using static method in class (rather than export function) work ?
  • Any other way to that ?
Asoub
  • 2,273
  • 1
  • 20
  • 33
  • when you say spy on `fooutils`, you mean `spyOn(fooutils, "getData")`, right? I would expect that to work – pushkin Oct 16 '20 at 14:38
  • @pushkin sorry it's been a real long time, I'm not on this project anymore, but I think that I tried that yes (maybe now it works). – Asoub Dec 05 '20 at 13:32

1 Answers1

0

You can wrap getData in an object { getData } and write your unit test as follows.

import { getData } from "../utils/foo.utils";

...

it(" should do stuff", () => {
  const spy = spyOn({ getData }, "getData").and.returnValue([]);
  bar.do();
  expect(spy).toHaveBeenCalled();
});
uminder
  • 23,831
  • 5
  • 37
  • 72