1

Given the following class:

class Foo {
  public bar(): Bar;
  public bar(string): Bar;
}

I want to stub only the first bar() method, how should I do that or is there any workarounds?

Jack Guo
  • 3,959
  • 8
  • 39
  • 60

1 Answers1

2

Not exactly

You can't do this. Typescript's overloaded methods don't exist at run time - they compile down to a single method.

From the typescript documentation:

TypeScript can only resolve a function call to a single overload

See this excellent answer to a different question for some discussion.

There's also this blog post which has the following example:

    public getHero(name: string): Hero {
        return /* some code here */
    }

    public getHero(name: string, skill: string): Hero {
        return /* some other code here */
    }

A breakpoint in the second function is hit when the first function is called, because Typescript has compiled away the two functions into one.


A workaround

However if you need exactly this behaviour - you can make a complex stub that will allow you to call the underlying implementation in some cases using wrappedMethod and callsFake (documentation link here):

        sinon
            .stub(foo, "bar");

         foo.bar.callsFake(function mockBar(maybeString?: string) {
             if (string === undefined) { /* stub behaviour */}
             else { return foo.bar.wrappedMethod(maybeString) }                
         });


An aside

As an aside, I would advise against complex stubbing, because now you are in a situation where it would be appropriate to write tests for your tests - in my view, it would be better to refactor the code so that this kind of stubbing is not necessary.

Timothy Jones
  • 21,495
  • 6
  • 60
  • 90
  • When I do `sinon.stub(foo, "bar").withArgs()`, I got `Expected 1 arguments, but got 0` error at the `withArgs()` line. – Jack Guo Dec 31 '21 at 00:38
  • @JackGuo Quite right. I've updated the answer – Timothy Jones Dec 31 '21 at 03:02
  • it still doesn't work. I noticed that whenever I use callsFake in this scenario, it gets stuck in an infinite loop at line sinon/proxy-invoke.js:50:47. I tried the withArgs() approach again with @ts-ignore, but it seems to be invoked for the bar(string) method as well. – Jack Guo Dec 31 '21 at 17:35
  • Problem solved: https://stackoverflow.com/questions/70544581/cloud-function-unit-test-mock-new-document-id/70544860#70544860 – Jack Guo Dec 31 '21 at 19:02