Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

td.callback, when given a td.object, raises a TypeError #124

Closed
davetron5000 opened this issue Aug 21, 2016 · 8 comments · Fixed by #301
Closed

td.callback, when given a td.object, raises a TypeError #124

davetron5000 opened this issue Aug 21, 2016 · 8 comments · Fixed by #301

Comments

@davetron5000
Copy link

This is on 1.6.0 of testdouble.js and 3.10.1 of lodash

Given this code:

var td = require("testdouble");

var beingTested = {
  functionToTest: function(thing) {
    var self = this;
    thing.subscribe(
      function(response) {
        self.data = response.json().data;
      },
      function(error) {
      }
    );
  }
}

describe("", function() {
  it("", function() {
    var data = [
      {
        id: 1,
        name: "foo"
      },
      {
        id: 2,
        name: "bar"
      }
    ];
    var mockThing = td.object("subscribe");
    var mockResponse = td.object("json");
    /*
    var mockResponse = {
      json: td.function()
    }
    */
    td.when(mockThing.subscribe(td.callback(mockResponse),td.matchers.anything())).thenReturn();
    td.when(mockResponse.json()).thenReturn( { data: data });

    beingTested.functionToTest(mockThing);

    expect(beingTested.data).toBe(data);
  });
});

I get this output:

> node_modules/.bin/jasmine-node spec/javascripts/td.spec.js 
F

Failures:

  1)  
   Message:
     TypeError: Cannot convert a Symbol value to a string
   Stacktrace:
     TypeError: Cannot convert a Symbol value to a string
    at Object.Proxy.get (/Users/davec/Projects/rails-book/shine/node_modules/testdouble/lib/object.js:59:75)
    at Function.isString (/Users/davec/Projects/rails-book/shine/node_modules/lodash/index.js:8978:78)
    at module.exports (/Users/davec/Projects/rails-book/shine/node_modules/testdouble/lib/stringify/anything.js:10:11)
    at /Users/davec/Projects/rails-book/shine/node_modules/testdouble/lib/stringify/arguments.js:17:30
    at arrayMap (/Users/davec/Projects/rails-book/shine/node_modules/lodash/index.js:1406:25)
    at map (/Users/davec/Projects/rails-book/shine/node_modules/lodash/index.js:6710:14)
    at interceptor (/Users/davec/Projects/rails-book/shine/node_modules/lodash/index.js:12240:26)
    at thru (/Users/davec/Projects/rails-book/shine/node_modules/lodash/index.js:5927:26)
    at baseWrapperValue (/Users/davec/Projects/rails-book/shine/node_modules/lodash/index.js:2768:30)
    at LazyWrapper.lazyValue [as value] (/Users/davec/Projects/rails-book/shine/node_modules/lodash/index.js:1077:16)

Finished in 0.014 seconds
1 test, 1 assertion, 1 failure, 0 skipped


(node:8884) DeprecationWarning: util.print is deprecated. Use console.log instead.

If I replace

 var mockResponse = td.object("json");

with

    var mockResponse = {
      json: td.function()
    }

everything works.

I looked into the code, but can't understand what's going on enough to be more helpful :(

@searls
Copy link
Member

searls commented Aug 21, 2016

(Forgive me for just reading the bottom of this issue but I think based on the conclusion I know what you're asking. We'll reopen if I'm wrong)

The API td.object does some serious heavy lifting. When you provide it a string (as you did with td.object("json"), it will assume you want to use an ES2015 Proxy object (a sort of blank slate double that you or I might be familiar with in Rubyland) which will respond to anything and everything you call on it (that is, if your runtime supports ES2015 Proxy)

If what you want, as your example indicates, is a bag of functions, then you should pass them as an array of strings. In your case:

td.object(['json']);

This will give you a plain old javascript object that has json property set to a test double function.

@searls searls closed this as completed Aug 21, 2016
@davetron5000
Copy link
Author

OK, that fixed it. Thanks for the fast response!

How could I tell if my runtime supports an ES2015 Proxy? All of this is just ES5, so presumably that means it doesn't? And is that why I get this error, i.e. if I did have support for ES2015 Proxy objects, it would've worked as expected (even thought it was certainly not what I was intending :)?

@searls
Copy link
Member

searls commented Aug 21, 2016

Proxy is a global so new Proxy() should be enough to test. Otherwise caniuse, etc

@davetron5000
Copy link
Author

It appears defined for me. Also, the real test I extracted this example from has other uses of var blah = td.object("someMethodIPlanToStub") and those work without an exception—this exception only comes up if I pass the object to td.callback().

I also tried a few other things:

var mockResponse = td.object("Response"); // but still calling JSON

and

var mockResponse = td.object("Response"); // but still calling JSON
mockResponse.json; // to see if this establishes the function in advance
mockResponse.json(); // also to see if this establishes the function in advance

Those all had the same error result as before.

@davetron5000
Copy link
Author

And to be clear, I acknowledge that I'm using it wrong, but this behavior seems odd to me and many minutes of experience with this library :)

@davetron5000
Copy link
Author

Per discussion on twitter:

  • Problem exists in node
  • Problem exists in Chrome
  • Problem does not exist in Firefox

@searls
Copy link
Member

searls commented Aug 21, 2016

Figures. Paging @jasonkarns to commiserate

@searls
Copy link
Member

searls commented Sep 15, 2016

@davetron5000 I think my next course of action is to add a node 7 specific tests since we never had firefox in CI i don't think

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants