简体   繁体   中英

Ensure spyOnProperty creates configurable properties with Object.defineProperty

In an upgrade to Angular 9 (from 8.1) and Typescript 3.7 (from <3.6), I have encountered an issue with spyOnProperty

My service looks like:

class Backend {
  public get baseURL(): string {
    return 'http://baseurl.com/';
  }
}

My test that worked before the upgrade would spyOnProperty

spyOnProperty(backend, 'baseURL', 'get').and.returnValue('http://new');

However, I am now getting this error:

Error: <spyOnProperty> : baseURL is not declared configurable
Usage: spyOnProperty(<object>, <propName>, [accessType])

I know that I need to Object.defineProperty as configurable: true , as when stepping through Jasmine I see it fails at:

if (!descriptor.configurable) {
  throw new Error(
    getErrorMsg(propertyName + ' is not declared configurable')
  );
}

And descriptor is created by descriptor = Object.getOwnPropertyDescriptor(proto, methodName);

So in Javascript I would want to:

Object.defineProperty(backend.prototpye, 'baseURL', {value: 'http://new', configurable: true});

To ensure that this property could be spied on.

However, my question is how do I apply the same configurable with Typescript. I have tried to run Object.defineProperty again but I get an error defineproperty Cannot redefine property , which makes sense as to why the check is there in the first place.

I tried using the suggested configurable decorator defined here :

function configurable(value: boolean) {
    return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
        descriptor.configurable = value;
    };
}

But this does not work, also to note that when I put a breakpoint inside the above method, the descriptor.configurable is actually already set to true before assigning the value . So I am not sure what is actually causing the original error in the tests.

I missed some additional information about creating my tests. To create an instance of the injected services I am using, ts-mockito to create an instance() of each class.

I think it was this call to instance() that was creating properties as not configurable.

Effectively:

service = new Service(instance(new Backend));

Changed to:

service = new Service(new Backend);

Resolves the issue

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM