2

I'm trying to compare two higher order functions using jest matchers. I have already looked at how do I compare 2 functions in javascript and that doesn't answer my question.

it("should return a function based on regex",() => {
    const expectedFunc = (record) => RegExp("DATE").test(record.name)
    function filter(regex){
        return (record) => RegExp(regex).test(record.name)
    }
    expect( filter("DATE").toString()).toEqual(expectedFunc.toString())
})  

Result

should return a function based on regex

expect(received).toEqual(expected)

Expected value to equal:
  "record => RegExp(\"DATE\").test(record.name)"
Received:
  "record => RegExp(regex).test(record.name)"

Updated my test based on answer by Code-Apprentice

it("should return a function based on regex",() => {
    function filter(regex){
        return (record) => RegExp(regex).test(record)
    }
    expect( filter("DATE")("this record has DATE")).toEqual(true)
})
skyboyer
  • 22,209
  • 7
  • 57
  • 64
Ravi
  • 1,811
  • 1
  • 18
  • 31
  • 1
    These functions are not equal, uses a variable, that can be set to any value that is in `regex` but the other is a String. Therefore, these functions should not return as equal, ever. – Andria Jul 07 '18 at 15:42
  • That edit was a pretty massive change Ravi. It sounds like you have a different question potentially. – CollinD Jul 07 '18 at 15:43
  • Yeah I know. Apologize for that. I wanted to give a simple example. But after looking at answers I realized the initial question is totally incorrect – Ravi Jul 07 '18 at 15:45
  • @chbchb55 That depends on how you define "equal". In the sense that they are not textually the same code, then you are correct. However, from a testing perspective, this is not the right way to view equality. Instead a mathematical definition of function equality is more appropriate: two functions are equal if and only if `f(x) == g(x)` for all `x` in the domains of the functions. In programming terminology, this means to compare the return values of each function given the same argument to both. – Code-Apprentice Jul 07 '18 at 15:50
  • @Code-Apprentice I meant `equal` as in `.toEqual` should not return equal ever – Andria Jul 07 '18 at 15:56
  • @chbchb55 Even if `expect(f.toString()).toEqual(g.toString())` passes, the test is insufficient because it does not guarantee that the behavior of the function is correct. The code could be a copy-paste with the same errors. Testing functions in this way seems to be the incorrect approach to me. – Code-Apprentice Jul 07 '18 at 16:29
  • @Code-Apprentice It does guarantee that the behavior is the same, bc `.toString` returns the code. If the code is the same the behavior is the same. Granted, this test is only to check that two functions have the same code, that's all, its not to test if it works – Andria Jul 07 '18 at 16:35
  • @chbchb55 "its not to test if it works" That is what I mean by "guarantee that the behavior of the function is correct". Testing that two functions have the same code seems useless to me when you cannot test that the function works as intended. – Code-Apprentice Jul 07 '18 at 16:48
  • Yes @Code-Apprentice but that's clearly not the point of this test. Plus, if the functions are the same, now you only need to test one function and if the "functions are the same" test ever fails now you know you messed something up. – Andria Jul 07 '18 at 16:50
  • I'm sure this is different than the original intent of the OP. IMO, the correct testing approach here should be to validate the behavior of the returned function, not just validate the text of the code. – Code-Apprentice Jul 07 '18 at 16:59
  • 1
    If I may add something here. I wanted to test "does filter return a function that can take a string and return true or false based on the content of the string". And testing it based on data and not the function makes more sense. E.g basically I want to know if the function returned by filter is same as another fn that I have. And as per mathematics, the only way to test if two functions are same is to pass them values and test. https://math.stackexchange.com/questions/1403122/when-do-two-functions-become-equal – Ravi Jul 07 '18 at 16:59

1 Answers1

0

In general, you should not compare functions directly. Instead, you should compare the values that they return. If two functions perform the same calculation, you can check that they both return the same value for the same input:

const rec = {value: 42};
expect(tested(rec)).toEqual(fn1(rec))

Note how this calls both functions with the same argument and expects the returned value to be equal.

Code-Apprentice
  • 81,660
  • 23
  • 145
  • 268
  • Sorry, my initial was incorrect. I didn't put it correctly and gave a wrong example. Can you please check now – Ravi Jul 07 '18 at 15:36
  • @RaviR The same principle applies. You must comapre the return values. In this case, `filter()` returns a function which you must call. Then compare its return value with the return value from `expectedFunc()`. – Code-Apprentice Jul 07 '18 at 15:40
  • @RaviR Since you need to compare return the return value when you call the function returned by `filter()`, `expectedFunc()` is just an unnecessary complication. – Code-Apprentice Jul 07 '18 at 15:51
  • Wow!! Your answer made me understand some math concept I read long ago but never understood really. Now I understand why I cannot test like how I am doing it now. I searched a bit more and this post nailed it https://math.stackexchange.com/questions/1403122/when-do-two-functions-become-equal. Thanks!! – Ravi Jul 07 '18 at 15:55