The configuration of the property has not been declared (Error: <spyOnProperty>)

Imagine having a MenuComponent

@Component({
  selector: 'cg-menu',
  templateUrl: './menu.component.html',
  styleUrls: [ './menu.component.scss' ]
})
export class MenuComponent implements OnInit {
  menu: MenuItem[];

  isLoggedIn$ = this.authStateService.isLoggedIn.pipe(untilDestroyed(this));

  constructor(private readonly authStateService: AuthStateService,
              private readonly router: Router) {
  }

  ngOnInit() {
    this.authStateService
      .state
      .pipe(
        untilDestroyed(this),
        ...some logic...
      .subscribe();
  }

  ...some logic...
}

Now, consider a AuthStateService

@Injectable({ providedIn: 'root' })
export class AuthStateService {
  private readonly state$: Observable<AuthState | null>;
  private readonly isLoggedIn$: Observable<boolean | null>;

  constructor(private readonly sessionManager: SessionManagerService) {

    this.state$ = this.stateTrigger$
      .pipe(
        ...some logic...
        shareReplay(1));

    this.isLoggedIn$ = this.stateTrigger$
      .pipe(
        map(state => state !== null),
        shareReplay(1));
  }

  get state(): Observable<AuthState> {
    return this.state$;
  }

  get isLoggedIn(): Observable<boolean> {
    return this.isLoggedIn$;
  }

  ...some logic...
}

While attempting to execute this code, I encountered an error triggered by Karma.

describe('MenuComponent', () => {
  let component: MenuComponent;
  let fixture: ComponentFixture<MenuComponent>;

  let authStateServiceSpy;

  beforeEach(async(() => {
    authStateServiceSpy = jasmine.createSpyObj(
      'AuthStateService',
      {},
      {
        state: of(null),
        isLoggedIn: of(false)
      });

    TestBed.configureTestingModule({
      declarations: [ MenuComponent ],
      imports: [ RouterTestingModule ],
      providers: [
        { provide: AuthStateService, useValue: authStateServiceSpy }
      ],
      schemas: [ NO_ERRORS_SCHEMA ]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(MenuComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should generate correct menu (expert)', () => {
    // The problem is here
    spyOnProperty(authStateServiceSpy, 'state', 'get').and.callFake(() => of(stateMock));

    expect(component.menu).toEqual([
      ...something...
    ]);
  });
});

The specific error message reads as follows:

Error: <spyOnProperty> : state is not declared configurable
    Usage: spyOnProperty(<object>, <propName>, [accessType])
    Error: <spyOnProperty> : state is not declared configurable
    Usage: spyOnProperty(<object>, <propName>, [accessType])
        at <Jasmine>
        at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/src/app/modules/structure/components/menu/menu.component.spec.ts:55:5)
        at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:364:1)
        at ProxyZoneSpec.push../node_modules/zone.js/dist/zone-testing.js.ProxyZoneSpec.onInvoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:292:1)
        at ZoneDelegate.invoke (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:363:1)
        at Zone.run (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-evergreen.js:123:1)
        at runInTestZone (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:545:1)
        at UserContext.<anonymous> (http://localhost:9876/_karma_webpack_/node_modules/zone.js/dist/zone-testing.js:560:1)

Do you have any insights on what might be causing this issue? Thank you for your assistance.

Answer №1

Perhaps the issue arises because AuthStateService's state is implemented as a getter in the class, while your mock defines it as a regular property. To resolve this, make sure to declare it as a getter in your mock as well.

The problem may be attributed to the use of createSpyObj alongside spyOnProperty, especially when attempting to spy on a non-existent getter.

Upon reviewing your code, it appears that utilizing createSpyObj serves no particular purpose in this scenario. Adjusting your approach as follows could potentially solve the issue:

// ...

authStateServiceMock = {
    get state() { return of(null) },
    get isLoggedIn() { return of(false) },
};

// ...

spyOnProperty(authStateServiceMock, 'state', 'get').and.callFake(() => of(stateMock));

expect(component.menu).toEqual([
    ...something...
]);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can one assess a private method within a class?

Within my Ionic 3 (Angular 4) application, I am working with the following code snippet: this.$observable.subscribe(success => { if (success) { this.toastCtrl.create({ message: 'message, duration: 3000, position: 'midd ...

Building a Dynamic Checkbox Validation Feature in Angular Using Data retrieved from an API

Currently, I have a function that retrieves and displays a list obtained from an API: displayEventTicketDetails() { this.Service .getEventTicketDetails().subscribe((data: any) => { this.eventTicketDetails = data.map(ticket => ticket. ...

`Developing reusable TypeScript code for both Node.js and Vue.js`

I'm struggling to figure out the solution for my current setup. Here are the details: Node.js 16.1.x Vue.js 3.x TypeScript 4.2.4 This is how my directory structure looks: Root (Node.js server) shared MySharedFile.ts ui (Vue.js code) MySharedFi ...

Error message 2339 - The property 'toggleExpand' is not recognized on the specified type 'AccHeaderContextProps | undefined'

When utilizing the context to share data, I am encountering a type error in TypeScript stating Property 'toggleExpand' does not exist on type 'AccHeaderContextProps | undefined'.ts(2339). However, all the props have been declared. inter ...

The Angular2-Recaptcha feature fails to load when navigating back in the browser

As I delve into the world of Angular Application development, I encounter an issue with Recaptcha. Everything works smoothly during application initialization. However, upon navigating to the next page and then attempting to go back using the browser' ...

Issues with the linear-gradient feature in Ionic3 are preventing it from properly functioning

I'm currently experimenting with creating a unique gradient color in my Ionic3 variable.sass file. $colors: ( primary: #4471C1, secondary: #32db64, danger: #f53d3d, light: #f4f4f4, dark: #222, newcolor: linear-gradient( ...

What could be the root of this next.js build issue occurring on the Vercel platform?

I recently upgraded my next.js project to version 12.0.7, along with Typescript (4.5.4) and pdfjs-dist (2.11.228), among other libraries. Locally, everything runs smoothly with the commands yarn dev for development and yarn build for building. However, af ...

Unexpected token in catch clause in React Native TypeScript

Despite having a fully configured React Native Typescript project that is functioning as expected, I have encountered a peculiar issue: Within all of my catch blocks, due to the strict mode being enabled, typescript errors are appearing like this one: My ...

You must add the module-alias/register to each file in order to use path aliases in

I am currently utilizing typescript v3.6.4 and have the following snippet in my tsconfig.json: "compilerOptions": { "moduleResolution": "node", "baseUrl": "./src", "paths": { "@config/*": ["config/*"], "@config": ["config"], ...

Connecting attribute in Angular 5 through @Input

(UPDATED) I originally had a basic jarallax setup with just a div containing the corresponding configuration in a component: <div class="view cover-jarallax" data-jarallax="{"speed": '0.w'}" style="background-image: url(imgurl);' + &apo ...

Establishing default query parameters during the routing process

Here is the current route configuration I am working with: const routes: Routes = [ // other routes { component: UsersListComponent, path: 'users' } ]; I am looking to automatically add default QUERY parameters whenever a route goes to this ...

Unit testing in Jest using Luxon: Is there a way to mock the .setZone('local') function?

I have a straightforward date component that I've been working on: import { DateTime } from 'luxon'; export const DateComponent = ({ item, itemKey }) => { const isoDateString = item[itemKey]; if (!isoDateString) { return ...

Exploring ways to interact with an API using arrays through interfaces in Angular CLI

I am currently utilizing Angular 7 and I have a REST API that provides the following data: {"Plate":"MIN123","Certifications":[{"File":"KIO","Date":"12-02-2018","Number":1},{"File":"KIO","Date":"12-02-2018","Number":1},{"File":"preventive","StartDate":"06 ...

Bring in all Functions and Interfaces from the Types Definition

How can I call the function below in TypeScript: nlp.text("Hi Dr. Miller the price is 4.59 for the U.C.L.A. Ph.Ds.").sentences.length // 1 To make this function call work, what would be the correct import statement needed from this types definition? It& ...

Unresponsive Textbox Input Issue within Reactive Form

My current setup involves an Angular Reactive Form with various controls: this.taskForm = this.formBuilder.group({ storyNumber: new FormControl('', [Validators.required, Validators.pattern('^[A-Z]{2,}[0-9]*-[0-9]{2,}$')]), ...

Ways to interpret and fix a conflict in npm dependency and understand the output

I'm encountering some issues while attempting to set up my project. The errors I'm running into during the installation process are: npm ERR! code ERESOLVE npm ERR! ERESOLVE could not resolve npm ERR! npm ERR! While resolving: @angular-devkit/< ...

What is the Angular2 version of angular.equals?

Currently, I am in process of upgrading an Angular 1 project to Angular 2. In the old project, I used angular.equals for comparing objects like this: angular.equals($ctrl.obj1, $ctrl.newObj);. I tried looking online for a similar method in Angular 2 but ...

React with Typescript: It appears that you are attempting to utilize Typescript without having it properly installed on your system

I am embarking on creating a React application integrated with TypeScript. Initially, I visited the React website to seek guidance on incorporating TypeScript in my project. The website directed me to execute the following command in the terminal: npx crea ...

How can I configure nest.js to route all requests to index.html in an Angular application?

I am developing an Angular and NestJS application, and my goal is to serve the index.html file for all routes. Main.ts File: async function bootstrap() { const app = await NestFactory.create(AppModule); app.useStaticAssets(join(__dirname, '..&ap ...

Building dynamic input forms within Angular2

In order to customize the form for each guest, I aim to prompt users to provide their name, grade, and age for every guest they wish to invite. Initially, I inquire about the number of guests they plan to have. Subsequently, I intend to present a tailored ...