angular-restmod icon indicating copy to clipboard operation
angular-restmod copied to clipboard

Best Way to Mock Restmod?

Open mindmelting opened this issue 11 years ago • 7 comments

What is the best way to mock and resolve the $save without actually making the http request in Jasmine?

profile.$save().$then(function () {
    vm.loading = false;
    NavigationService.next();
});

E.g. I want to test that NavigationService.next gets called, without caring about the HTTP request...

Any suggestions would be appreciated!

mindmelting avatar Dec 10 '14 17:12 mindmelting

This is something that definitely needs improvement.

We currently mock the requests, I've been thinking about this but I'm not really sure about which methods should be mocked. Any suggestions?

One possibility would be to provide something like FactoryGirl, let the user provide some test data, sequences, etc and mock everything that generates a request.

@blackjid, @bunzli what do you guys think about this?

iobaixas avatar Dec 10 '14 18:12 iobaixas

I originally tried mocking $save and returning a $q promise, but then I realised restmod uses $then instead of then (without using $asPromise) so it did not work :'(

I was going to mock the request, but if this is a call that is a child of another model, then working out what the request looks like can be a bit troublesome... So not really sure what the answer is right now...

mindmelting avatar Dec 10 '14 18:12 mindmelting

We've been mocking at the restmod layer (not at request). Here's a utility method we use (sorry, it's in typescript, but should be easy enough to convert):

export function mockRestmodResponse(value: any) {
  inject(($q: ng.IQService) => {
    var deferred = $q.defer();
    value.$asPromise = value.$asPromise || (() => { return deferred.promise; });
    value.$then = value.$then || (deferred.promise.then.bind(deferred.promise));
    value.$preload = value.$preload || (() => { return value; });

    deferred.resolve(value);
  });

  return value;
}

You can pass it either a plain object which it will convert to a pseudo restmod object, or you can pass it a restmod model you created using $new or $build or something.

The tricky part is you have to mock out prototypes, and relations are annoying. For instance, you mock ModelType.prototype.$save or for a relationship Object.getPrototypeOf(ModelType.$new().relation.$new().$save).

I would definitely welcome some better built-in support for mocking from restmod, but we've been able to make things work acceptably well so far.

scriby avatar Dec 10 '14 19:12 scriby

Just as an update to this, I ended up doing something along these lines:

var thenSpy = jasmine.createSpy();

spyOn(model, '$save').and.callFake(function () {
    return {
        $then: thenSpy
    };
});

thenSpy.calls.mostRecent().args[0]();

It's not perfect but works for what I need to test....

mindmelting avatar Dec 12 '14 08:12 mindmelting

@blackjid, @bunzli, maybe this could be a nice enhancement to be build during Platanus Fridays...

@ldlsegovia and @ReneMoraales I would very much appreciate your take on this too!

iobaixas avatar Jan 07 '15 01:01 iobaixas

@iobaixas, of course! I'm in

ldlsegovia avatar Jan 07 '15 13:01 ldlsegovia

Curious if there has been any further development on this? It seems to be the one thing none of these angular model modules have. Or if anyone has any other resources for testing?

NorthMcCormick avatar Apr 07 '16 13:04 NorthMcCormick