Override computed() property in test

After updating to Ember 3.9, we now get a bunch of these deprecation warnings: https://deprecations.emberjs.com/v3.x/#toc_computed-property-override

For places in our application where we use this, the steps to “fix” the deprecation make sense and we’ll gladly follow them.

However, there are some instances where we override a computed() property in a unit test, e.g. to mock certain things. These places now also trigger this deprecation. For example:

myProperty: computed(function() {
  // do some complex stuff that depends on a bunch of other properties...
  return myProperty;
})

In the test:

let component = this.owner.factoryFor('component:my-component').create({
  myProperty: mockedProperty
});

It doesn’t feel nice to add a setter and an internal private property etc. just so this can be mocked in a test… Are there any other patterns or ideas on how to tackle this in a nice, non-deprecation-triggering way?

I believe the deprecation is only triggered when you “clobber” the computed property, in your case you can override it by extending.

Something like this:

import FooService from 'my-app/services/foo';

test('asdf', function(assert) {
  this.owner.register('service:foo', FooService.extend({
    myProperty: mockedProperty
  });

  let service = this.owner.lookup('service:foo');
  // do stuff....
});

Note: I specifically changed the example to use a service instead of a component (though the technique I am describing is unrelated to the object type). In general, its not a good idea to manually instantiate components as it leads to brittle tests across Ember upgrades.

4 Likes

Ah, extending it in the test is a neat idea. I’ll try that out - thanks!

I actually did just trying this in a test for a component.

Below, I am trying to override both subtotal and taxRate (both of which are computed) to generate an expected total (also expected).

`import ShoppingCartComponent from ‘garcon/app/components/shopping-cart’

module(‘taxes’, function() { test(“the computed property taxes returns the subtotal * the taxRate/100”, function(assert) {

  this.owner.register('component:shopping-cart', ShoppingCartComponent.extend({
    subtotal: 99,
    taxRate: 22
  }));

  let shoppingCart = this.owner.lookup('component:shopping-cart');

  assert.equal(shoppingCart.taxes, 12.5, "taxes is 12.5");
});

});`

This throws the following error: Error: Could not find module 'garcon/app/components/shopping-cart' imported from 'garcon/tests/integration/components/shopping-cart-test'.

What am I missing? The component is in the location I set in the import.

You need to import from garcon/components/... (instead of garcon/app/...).