3

How can I use the Sinon package to stub/mock a method call where one of the parameters I have to mock is called using an arrow function? eg

let objWithMethod = { method : function(x) {}; };
function SUT() {
    // use case
   let x = 'some value';
   let y = { anotherMethod : function(func) {}; };

   // I want to test that `y.anotherMethod()` is called with
   // `(x) => objWithMethod.method(x)` as the argument
   y.anotherMethod((x) => objWithMethod.method(x));
}

let mockObj = sinon.mock(objWithMethod);

// Both of these fail with a "never called" error
mockObj.expects('method').once().withArgs(objWithMethod.method.bind(this, x));
mockObj.expects('method').once().withArgs((x) => objWithMethod.method(x));

SUT();
mockObj.verify();

I couldn't find anything in the sinon docs nor after a few attempts at a google search.

Derek
  • 4,575
  • 3
  • 22
  • 36
  • You don't access `objWithMethod.method` in your code. `objWithMethod` is an object, while you call it as a function. How does it even work? – zerkms Jul 15 '16 at 03:10
  • Your code causes `VM604:5 Uncaught TypeError: objWithMethod is not a function` (after you fix a problem with extra `;` in the first line) – zerkms Jul 15 '16 at 03:12
  • you're right my example is not correctly representing what im asking i will update it – Derek Jul 15 '16 at 03:12
  • updated to reflect what i meant – Derek Jul 15 '16 at 03:16
  • Even after update - you don't invoke `objWithMethod.method` in your code. – zerkms Jul 15 '16 at 03:16
  • @zerkms correct, i'm not actually calling it, i'm passing it as a value (wrapped in an arrow function) into the method call in `y.anotherMethod()` – Derek Jul 15 '16 at 03:17
  • So? What is the problem then? – zerkms Jul 15 '16 at 03:18
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/117366/discussion-between-zerkms-and-derek). – zerkms Jul 15 '16 at 03:18
  • The problem is no different from a call where the argument is a standard function expression, and not exactly specific to ES6 either. – Bergi Jul 15 '16 at 04:29
  • `objWithMethod.method` is not called with the function, it's called with `x`. You probably want to test `.withArgs('some value')`, and your test will succeed when you change `anotherMethod` to call `func(x)` in its body. – Bergi Jul 15 '16 at 04:31

1 Answers1

0

Loose matches you're trying to do can be done with matchers, to compare against any function it should be

mockObj.expects('method').withArgs(sinon.match.func)

And it will fail, because objWithMethod.method isn't called at all.

This

// I want to test that y.anotherMethod() is called with

// (x) => objWithMethod.method(x) as the argument

cannot be done, because the code wasn't written with tests in mind. JS can't reflect local variables, and SUT function is a blackbox.

In order to be reachable for tests and get 100% coverage, each and every variable and closure should be exposed to the outer world.

Community
  • 1
  • 1
Estus Flask
  • 206,104
  • 70
  • 425
  • 565