Error: <spyOnProperty> : function is not declared configurable
Asked Answered
C

4

17

I had working jasmine tests with webpack 3. Now I try to use it with webpack 4 but have some problem with it.

Firstly I had problem with spyOn function.

Error: : myFunction is not declared writable or has no setter

I found some articles about some workaround for this problem: spy-on-getter-and-setter

I changed spyOn to spyOnProperty but with no luck. Now I have problem with

> Error: : myFunction is not declared configurable

My code is written in js and looks like this:

import * as FocusServiceSpy from '../focus/FocusService';

describe('#onLinkClick', function() {
            it('should call myFunction', () => {
                spyOnProperty(FocusServiceSpy, 'myFunction', 'get');
                expect(FocusServiceSpy.myFunction).toHaveBeenCalled();
            });

        }

Do you know what could be a problem with this?

UPDATE 1:

I should be more descriptive. I would like to create spy on function of the FocusService. This service has only one method called myFunction. Only thing I want to achieve is to ensure that this method will be called.

Now I changed it to sth like this and have error:

>TypeError: Object is not a constructor (evaluating 'new FocusService()') (line 180)

describe('#onLinkClick', function() {
        const FocusService = require('../focus/FocusService');

        it('should call myFunction', () => {
            const service = new FocusService();
            spyOnProperty(service, 'myFunction').and.callThrough();
            ... (do some action)
            expect(service.myFunction).toHaveBeenCalled();
        });

    }

FocusService looks like this:

export function myFunction(arg) {
    ... (do some action)
}
Charis answered 14/11, 2019 at 8:40 Comment(0)
O
7

In your unit test, I can see several problems. First you need to understand that spyOnProperty installs a spy on a property onto an existing object but it does not invoke the getter itself.

  1. You don't create an object nor provide it to spyOnProperty.

  2. You invoke spyOnProperty with a function name instead of a property name.

Your test could be structured as follows:

it('should call myFunction', () => {

    // given
    const service = new FocusService(); 
    const spy = spyOnProperty(service , 'myProperty', 'get').and.callThrough();

    // when
    const myProperty = service.myProperty; 

    // then
    expect(myProperty).toBe(<expected value>);
    expect(spy).toHaveBeenCalled();
});
Ormond answered 14/11, 2019 at 9:48 Comment(2)
Since FocusService is not a class, https://mcmap.net/q/135386/-using-jasmine-to-spy-on-a-function-without-an-object may give you some hint to solve your problemOrmond
This worked for us!Musical
N
2

I have experienced the same problem when I tried to upgrade project from Angular 8 to 9, there is no answer that I could find on Google, however I figured out a way how to solve it in my project.

In tsconfig.json, change target to es5.

Example:

{
  "compilerOptions": {
    ...
    "target": "es5",
    ...
  }
}

That's it! Hope this could help someone is trying to find the solution.

Nebula answered 12/11, 2020 at 7:5 Comment(2)
This changes the output of the compiled code. This isn't a good solution for people who want to deploy modern ES6+ code.Ricardo
@Ricardo Then you can change the target in tsconfig.spec.json.Clothes
K
1

With the newer version of Jasmine, the mutation of spies are not allowed and throws the above error for the member of the spy you are trying to modify.

Altering the definition of a spy's property isn't recommended as Jasmine explicitly disallows the members to be configurable.

Add the following code to your entry test file if you don't want this limitation to be forced upon you.

const defineProperty = Object.defineProperty;
Object.defineProperty = (o, p, c) => defineProperty(o, p, Object.assign({}, c ?? {}, { configurable: true }));

The code above forces every property, that is defined during the test run, to be marked as configurable.

Knipe answered 30/8, 2021 at 8:51 Comment(2)
It didn't help. I placed this code in src/test.ts.Reichsmark
Didn't help, also added to the end of src/test.tsCharactery
C
0

add configure({ safeDescriptors: false }); after the imports in Classdefinition file and it works with the properties

Cardiomegaly answered 19/7, 2023 at 17:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.