How do I mock a service in an ember-cli acceptance test?


#1

I’m developing an app that uses cookies for sessions. When a user visits the ember app without the cookie set, it should redirect to the sign-in page (not an ember app). I have a cookie service that handles cookie access, and I need to mock this for testing. Where do I put the mocked cookie service, and how do I tell the acceptance test to use the mocked service? This article hints at how to do it but shows how to do it only for route tests.

application route:

// app/routes/application.js
import Ember from 'ember';
export default Ember.Route.extend({
  beforeModel: function(transition) {
    if(!this.cookieService.get("auth_token")){
      window.location.replace("http://example.com");
    }
  },
});

cookie service:

// app/services/cookie.js
import Ember from 'ember';
export default Ember.Object.extend({
  get: function(key) {
    return $.cookie(key);
  },
  set: function(key, value) {
    $.cookie(key, value);
  },
});

acceptance test:

module('Acceptance: Authentication', {
  setup: function() {
    App = startApp();
    window.app = App;
  },
  teardown: function() {
    Ember.run(App, 'destroy');
  }
});

test('visiting root while not authenticated', function() {
  // Unset auth_key here using mock cookie service
  visit('/');
  andThen(function() {
    equal(currentURL(), 'example.com');
  });
});

#2

I was stuck on something kind of similar a few days ago. Two suggestions:

  1. You probably don’t want to be mocking services in your acceptance tests if you can avoid it.

  2. To avoid that you can either unset the cookie before your test starts or (better I think) add a method to clear out the cookie as part of the setup

     // app/services/cookie.js
     export default Ember.Object({
       // keep the rest of your code here
       clear: function(key){
         $.deleteCookie(key);
       }
     });
    
      // tests/integration/whatever.js
      module('Acceptance: Authentication', {
        setup: function(container) {
          App = startApp();
          window.app = App;
          App.__container__.lookup('service:cookie').clear('auth_key')
        },
        teardown: function() {
          Ember.run(App, 'destroy');
        }
     });

#3

In the article you linked, the slides from the talk go through mocking depedencies in acceptance tests, starting at slide 46.


#4

I tried using the method mentioned in those slides, but it doesn’t seem to work when using Ember-CLI.

I posted a detailed question on stackoverflow – it looks like the custom resolver in Ember-CLI doesn’t play nicely with unregistering the original service and registering a replacement mock service. The container will always get the original service’s module and not use the newly registered mock service.

This is not sufficient:

application.__container__.unregister('service:logger');
application.register('service:logger', mockLogger, {instantiate: false});

I had to modify the resolver to allow my app to actually use the mock service implementation… which doesn’t seem like it should be necessary.

Does anyone know how to do this properly?