0

Is it possible to get sinon to resolve an argument, when the argument is a defered object?

Consider this:

function needToTest() {
  var isInitialized = q.defer();
  var importantResult;
  var publicStuff;
  publicStuff.isInitialized = isInitialized.promise.then(function(res) {
    importantResult = res;
  });
  var someClass = new SomeClass(isInitialized);
  publicStuff.getResult = function() {
    return importantResult;
  };
  return publicStuff;
}

I use q as promise library, but it's not important. SomeClass looks something like this:

function SomeClass(promise) {
  this.foo = function() {
    //
  };
  //after some initializing:
  var result = true; //or false
  promise.resolve(result);
}

It might be that this mock should have some sort of function to resolve a promise, but this is what I have so far:

  var someClassMock = sinon.stub().withArgs(q.defer());
  someClass.prototype.foo = sinon.stub().returns('foo');
  return someClassMock;

and ultimately I try to create a testcase using sinon and Squire like this:

describe('test', function() {
  var needToTestInstance;
  beforeEach(function(done) {
    new Squire()
      .mock('someClassMock', someClassMock)
      .require(['needToTest'], function(module) {
        needToTest = module;
        //Need to get the needToTest().isInitialized to resolve with a value!
        done();
      });
  });
  describe('importantResult', function() {
    expect(needToTestInstance.getResult()).to.be(true);
  });
});

Is it possible to get isInitialized to resolve at any point in the test?

MrMamen
  • 359
  • 2
  • 14
  • You're not passing a promise, you're passing a deferred object. – Bergi Nov 03 '20 at 13:41
  • You are right, I need to update the question slightly, but the main issue remains, how I resolve this in a test case? – MrMamen Nov 03 '20 at 13:42
  • Your `needToTest` is very confusing. What is `current`, and where is `current.isInitialized` used? Why is `getResult` not used anywhere, and why do you have the `importantResult` variable at all instead of just using the promise? – Bergi Nov 03 '20 at 13:44
  • 1
    You would need to mock `SomeClass` with a function that calls `.resolve()` on its first argument. It's just like calling a callback. However, I generally advise [not to do any asynchronous stuff in constructors](https://stackoverflow.com/q/24398699/1048572), not returning promises nor taking callbacks/deferreds as arguments. You might want to reconsider your overall design - this might also make both `SomeClass` and `needToTest` easier to test. – Bergi Nov 03 '20 at 13:47
  • How do I mock SomeClass with a function that does something with the first argument? I did create someClassMock, but calling someClassMock.returnsArg(0) in my test where the comment line is doesn't seem to return a promise. Possible because of different initialization of the same object? – MrMamen Nov 04 '20 at 07:12
  • No, your `SomeClass` is a constructor, it does not `return` its argument. You either do `sinon.stub().callsFake(defer => …)` and can do `defer.resolve()` or something in there, or you do nothing inside it and then afterwards do `someClassMock.firstCall.args[0].resolve()` – Bergi Nov 04 '20 at 07:58

0 Answers0