---
title: Bitovi Academy - Testing Selectors
description: Learn how to write unit tests for NgRx Selectors.
---

- ![AI implementation](https://www.bitovi.com/hubfs/AIConsultingIcon.svg)
  
  [AI implementation](https://www.bitovi.com/services/ai-consulting?hsLang=en-us)
- ![Systems engineering](https://www.bitovi.com/hubfs/icon%20-%20backend.svg)
  
  [Systems engineering](https://www.bitovi.com/services/systems-engineering-consulting?hsLang=en-us)
- ![Project management](https://www.bitovi.com/hubfs/icon%20-%20PM.svg)
  
  [Project management](https://www.bitovi.com/services/agile-project-management-consulting?hsLang=en-us)
- ![Product design](https://www.bitovi.com/hubfs/icon%20-%20design.svg)
  
  [Product design](https://www.bitovi.com/services/product-design-consulting?hsLang=en-us)
- ![Frontend development](https://www.bitovi.com/hubfs/icon%20-%20frontend.svg)
  
  [Frontend development](https://www.bitovi.com/services/frontend-development-consulting?hsLang=en-us)
- [View more
  
  →
  
  ](https://www.bitovi.com/digital-consulting-services?hsLang=en-us)

We're Experts in...

- [JavaScript](https://www.bitovi.com/services/frontend/javascript-consulting?hsLang=en-us)
- [AI training](https://www.bitovi.com/ai-training-for-software-engineers?hsLang=en-us)
- [Angular](https://www.bitovi.com/services/frontend/angular-consulting?hsLang=en-us)
- [Design Systems](https://www.bitovi.com/services/axure-figma-migration?hsLang=en-us)
- [React](https://www.bitovi.com/services/frontend/react-consulting?hsLang=en-us)
- [Temporal](https://www.bitovi.com/services/backend/temporal-consulting?hsLang=en-us)
- [React Native](https://www.bitovi.com/services/frontend/react-consulting/react-native?hsLang=en-us)
- [Node.js](https://www.bitovi.com/services/backend/nodejs-consulting-1?hsLang=en-us)

Showcase

![Yum! Brands](https://www.bitovi.com/hubfs/yum-showcase-link-1.png)

[View case study](https://www.bitovi.com/en/bitovi-yum-case-study?hsLang=en-us)

More Projects

- [![Levi's](https://www.bitovi.com/hubfs/levis.svg)](https://www.bitovi.com/web-application-consulting-work/levis-ecommerce-responsive-redesign?hsLang=en-us)
- [![Christie's International Real Estate](https://www.bitovi.com/hubfs/christies.svg)](https://design.bitovi.com/christies)
- [![BAFS](https://www.bitovi.com/hubfs/bafs.svg)](https://www.bitovi.com/ux-design-consulting/ux-case-studies/bafs-ppp?hsLang=en-us)
- [View more
  
  →
  
  ](https://www.bitovi.com/our-software-consulting-work?hsLang=en-us)

Open Source Tools

We build powerful tools and open source them to support the community.

[See what we've built →](https://www.bitovi.com/open-source?hsLang=en-us)

- [![Blog](https://www.bitovi.com/hubfs/icon%20-%20blog.svg)
  
  BlogWe post about perfecting software delivery
  
  ](https://bitovi.com/blog)
- [![Partnerships](https://www.bitovi.com/hubfs/Handshake-1.svg)
  
  PartnershipsLearn about Bitovi's technology partners
  
  ](https://www.bitovi.com/partnerships?hsLang=en-us)
- [![Academy](https://www.bitovi.com/hubfs/limbo/icons/icon-academy.svg)
  
  AcademyFree courses to build delivery skills
  
  ](https://www.bitovi.com/academy/?hsLang=en-us)
- [![Open source tools](https://www.bitovi.com/hubfs/icon%20-%20open%20source.svg)
  
  Open source toolsUse our tools or contribute to our open source mission.
  
  ](https://www.bitovi.com/open-source?hsLang=en-us)

Let's Connect

- [![Discord](https://www.bitovi.com/hubfs/DiscordLogo.svg)
  
  Discord
  
  ](https://discord.gg/J7ejFsZnJ4)
- [![LinkedIn](https://www.bitovi.com/hubfs/LinkedinLogo.svg)
  
  LinkedIn
  
  ](https://www.linkedin.com/company/bitovi/)
- [![GitHub](https://www.bitovi.com/hubfs/GithubLogo.svg)
  
  GitHub
  
  ](https://github.com/bitovi/)

![Eggbot](https://www.bitovi.com/hubfs/build_assets/bitovi-limbo-cms-react/338/js_client_assets/assets/eggbot-LTGhdSGL.png)

Name *

Work Email *

Phone

What's your project?

Send

### Contact Us

(312) 620-0386contact@bitovi.com

- [ Advanced JavaScript ](https://www.bitovi.com/academy/learn-advanced-javascript.html?hsLang=en-us)
- [ DOM and jQuery ](https://www.bitovi.com/academy/learn-dom-jquery.html?hsLang=en-us)
- [ Debug JavaScript ](https://www.bitovi.com/academy/learn-to-debug-javascript.html?hsLang=en-us)
- [ Learn TypeScript ](https://www.bitovi.com/academy/learn-typescript.html?hsLang=en-us)
- [ Learn React Native ](https://www.bitovi.com/academy/learn-react-native.html?hsLang=en-us)
- [ Learn Web Components ](https://www.bitovi.com/academy/learn-web-components.html?hsLang=en-us)
- [ Agile Program Management With Jira ](https://www.bitovi.com/academy/learn-agile-program-management-with-jira.html?hsLang=en-us)
- [ Learn RxJS ](https://www.bitovi.com/academy/learn-rxjs.html?hsLang=en-us)
- [ Giving a Training ](https://www.bitovi.com/academy/training.html?hsLang=en-us)
- [ Learn Technology Consulting ](https://www.bitovi.com/academy/learn-technology-consulting.html?hsLang=en-us)
- [ Learn React ](https://www.bitovi.com/academy/learn-react.html?hsLang=en-us)
- [ Learn NgRx ](https://www.bitovi.com/academy/learn-ngrx.html?hsLang=en-us) 
    - [ Why NgRx ](https://www.bitovi.com/academy/learn-ngrx/why-ngrx.html?hsLang=en-us)
    - [ Getting Started ](https://www.bitovi.com/academy/learn-ngrx/getting-started.html?hsLang=en-us)
    - [ Installing NgRx ](https://www.bitovi.com/academy/learn-ngrx/ngrx-init.html?hsLang=en-us)
    - [ Creating Actions ](https://www.bitovi.com/academy/learn-ngrx/create-actions.html?hsLang=en-us)
    - [ Dispatching Actions ](https://www.bitovi.com/academy/learn-ngrx/dispatch-actions.html?hsLang=en-us)
    - [ Testing Actions ](https://www.bitovi.com/academy/learn-ngrx/test-actions.html?hsLang=en-us)
    - [ Create an API Effect ](https://www.bitovi.com/academy/learn-ngrx/create-api-effects.html?hsLang=en-us)
    - [ Testing API Effects ](https://www.bitovi.com/academy/learn-ngrx/test-api-effects.html?hsLang=en-us)
    - [ Creating Redirect Effects ](https://www.bitovi.com/academy/learn-ngrx/create-redirect-effects.html?hsLang=en-us)
    - [ Testing Redirect Effects ](https://www.bitovi.com/academy/learn-ngrx/test-redirect-effects.html?hsLang=en-us)
    - [ Create a Reducer ](https://www.bitovi.com/academy/learn-ngrx/create-reducer.html?hsLang=en-us)
    - [ Testing Reducers ](https://www.bitovi.com/academy/learn-ngrx/test-reducer.html?hsLang=en-us)
    - [ Creating Selectors ](https://www.bitovi.com/academy/learn-ngrx/create-selectors.html?hsLang=en-us)
    - [ Testing Selectors ](https://www.bitovi.com/academy/learn-ngrx/test-selectors.html?hsLang=en-us)
    - [ Using Selectors ](https://www.bitovi.com/academy/learn-ngrx/use-selectors.html?hsLang=en-us)
    - [ Testing Selector Use ](https://www.bitovi.com/academy/learn-ngrx/test-used-selectors.html?hsLang=en-us)
- [ Learn Graphql ](https://www.bitovi.com/academy/learn-graphql.html?hsLang=en-us)
- [ Learn Docker ](https://www.bitovi.com/academy/learn-docker.html?hsLang=en-us)
- [ Learn CanJS ](https://www.bitovi.com/academy/learn-canjs.html?hsLang=en-us)
- [ Learn Angular ](https://www.bitovi.com/academy/learn-angular.html?hsLang=en-us)
- [ Advanced TypeScript ](https://www.bitovi.com/academy/advanced-typescript.html?hsLang=en-us)

[View More Courses](https://www.bitovi.com/academy/#courses) [ ]

# Testing Selectors `page`

Learn how to write unit tests for NgRx Selectors.

> **Quick Start**: You can checkout [this branch](https://github.com/bitovi/angular-ngrx-chat/tree/create-selectors) to get your codebase ready to work on this section.

## Overview

1. Verify `selectUserId()` Selector returns `userId`.
2. Verify `selectUsername()` Selector returns `username`.
3. Verify `selectToken()` Selector returns `token`.

## Running Tests

To run unit tests in your project, you can either use the `test` npm script, or the `ng test` command:

```
npm run test
# or
ng test --watch
```

The `--watch` switch will rerun your tests whenever a code file changes. You can skip it to just run all tests once.

## Description

When testing Selectors, we will mock the Login State and verify that each Selector returns the expected result. Like testing the Reducer, we don’t need a `TestBed` since there shouldn’t be any dependencies when dealing with Selectors since they are pure functions.

## Update `login.selectors.spec.ts`

We will walk through updating `src/app/store/login/login.selectors.spec.ts` to run tests for your Selectors.

## Verify Feature State Selector

This test has already been written in a previous section where we were testing the Reducer ([Testing Reducers](https://www.bitovi.com/academy/learn-ngrx/test-reducer.html?hsLang=en-us)):

src/app/store/login/login.selectors.spec.ts

```
// src/app/store/login/login.selectors.spec.ts

import * as fromLogin from './login.reducer';
import { selectLoginState } from './login.selectors';

describe('Login Selectors', () => {
  it('should select the feature state', () => {
    const result = selectLoginState({
      [fromLogin.loginFeatureKey]: {
        ...fromLogin.initialState,
        userId: 'some-user-id',
        username: 'some-username',
        token: 'some-token',
      },
    });

    expect(result).toEqual({
      userId: 'some-user-id',
      username: 'some-username',
      token: 'some-token',
    });
  });
});

```

The Feature State Selector is unique to all other Selectors for a Feature Store because this Selector is the source for all other Selectors for a Feature Store and is the only Selector generated using the [`createFeatureSelector()`](https://ngrx.io/guide/store/selectors#selecting-feature-states) helper. Testing the Feature State Selector should be straight-forward since it should return all of the Login State.

## Verify `selectUserId` Selector Returns `userId`

To properly test Selectors in a way that ensures that each Selector does not rely on mutations on the Login State, we will use `beforeEach()` to create a fresh Login State per test:

src/app/store/login/login.selectors.spec.ts

```
// src/app/store/login/login.selectors.spec.ts

import * as fromLogin from './login.reducer';
import { selectLoginState } from './login.selectors';

describe('Login Selectors', () => {
  let state: fromLogin.LoginPartialState;

  beforeEach(() => {
    state = {
      [fromLogin.loginFeatureKey]: {
        ...fromLogin.initialState,
        userId: 'some-user-id',
        username: 'some-username',
        token: 'some-token',
      },
    };
  });

  it('should select the feature state', () => {
    const result = selectLoginState(state);

    expect(result).toEqual({
      userId: 'some-user-id',
      username: 'some-username',
      token: 'some-token',
    });
  });
});

```

Now we can write our tests for our Selectors. The first Selector we will test is the `selectUserId()` Selector:

src/app/store/login/login.selectors.spec.ts

```
// src/app/store/login/login.selectors.spec.ts

import * as fromLogin from './login.reducer';
import {
  selectLoginState,
  selectUserId,
} from './login.selectors';

describe('Login Selectors', () => {
  let state: fromLogin.LoginPartialState;

  beforeEach(() => {
    state = {
      [fromLogin.loginFeatureKey]: {
        ...fromLogin.initialState,
        userId: 'some-user-id',
        username: 'some-username',
        token: 'some-token',
      },
    };
  });

  it('should select the feature state', () => {
    const result = selectLoginState(state);

    expect(result).toEqual({
      userId: 'some-user-id',
      username: 'some-username',
      token: 'some-token',
    });
  });

  describe('selectUserId', () => {
    it('should return userId from login state', () => {
      const result = selectUserId(state);

      expect(result).toBe('some-user-id');
    });
  });
});

```

## Verify `selectUsername()` Selector Returns `username`

src/app/store/login/login.selectors.spec.ts

```
// src/app/store/login/login.selectors.spec.ts

import * as fromLogin from './login.reducer';
import {
  selectLoginState,
  selectUserId,
  selectUsername,
} from './login.selectors';

describe('Login Selectors', () => {
  let state: fromLogin.LoginPartialState;

  beforeEach(() => {
    state = {
      [fromLogin.loginFeatureKey]: {
        ...fromLogin.initialState,
        userId: 'some-user-id',
        username: 'some-username',
        token: 'some-token',
      },
    };
  });

  it('should select the feature state', () => {
    const result = selectLoginState(state);

    expect(result).toEqual({
      userId: 'some-user-id',
      username: 'some-username',
      token: 'some-token',
    });
  });

  describe('selectUserId', () => {
    it('should return userId from login state', () => {
      const result = selectUserId(state);

      expect(result).toBe('some-user-id');
    });
  });

  describe('selectUsername', () => {
    it('should return username from login state', () => {
      const result = selectUsername(state);

      expect(result).toBe('some-username');
    });
  });
});

```

## Verify `selectToken()` Selector Returns `token`

src/app/store/login/login.selectors.spec.ts

```
// src/app/store/login/login.selectors.spec.ts

import * as fromLogin from './login.reducer';
import {
  selectLoginState,
  selectToken,
  selectUserId,
  selectUsername,
} from './login.selectors';

describe('Login Selectors', () => {
  let state: fromLogin.LoginPartialState;

  beforeEach(() => {
    state = {
      [fromLogin.loginFeatureKey]: {
        ...fromLogin.initialState,
        userId: 'some-user-id',
        username: 'some-username',
        token: 'some-token',
      },
    };
  });

  it('should select the feature state', () => {
    const result = selectLoginState(state);

    expect(result).toEqual({
      userId: 'some-user-id',
      username: 'some-username',
      token: 'some-token',
    });
  });

  describe('selectUserId', () => {
    it('should return userId from login state', () => {
      const result = selectUserId(state);

      expect(result).toBe('some-user-id');
    });
  });

  describe('selectUsername', () => {
    it('should return username from login state', () => {
      const result = selectUsername(state);

      expect(result).toBe('some-username');
    });
  });

  describe('selectToken', () => {
    it('should return token from login state', () => {
      const result = selectToken(state);

      expect(result).toBe('some-token');
    });
  });
});

```

## Final Result

At the end of this section, the following spec file(s) should be updated. After each spec file has been updated and all the tests have passed, this means that all the previous sections have been completed successfully:

src/app/store/login/login.selectors.spec.ts

```
// src/app/store/login/login.selectors.spec.ts

import * as fromLogin from './login.reducer';
import {
  selectLoginState,
  selectToken,
  selectUserId,
  selectUsername,
} from './login.selectors';

describe('Login Selectors', () => {
  let state: fromLogin.LoginPartialState;

  beforeEach(() => {
    state = {
      [fromLogin.loginFeatureKey]: {
        ...fromLogin.initialState,
        userId: 'some-user-id',
        username: 'some-username',
        token: 'some-token',
      },
    };
  });

  it('should select the feature state', () => {
    const result = selectLoginState(state);

    expect(result).toEqual({
      userId: 'some-user-id',
      username: 'some-username',
      token: 'some-token',
    });
  });

  describe('selectUserId', () => {
    it('should return userId from login state', () => {
      const result = selectUserId(state);

      expect(result).toBe('some-user-id');
    });
  });

  describe('selectUsername', () => {
    it('should return username from login state', () => {
      const result = selectUsername(state);

      expect(result).toBe('some-username');
    });
  });

  describe('selectToken', () => {
    it('should return token from login state', () => {
      const result = selectToken(state);

      expect(result).toBe('some-token');
    });
  });
});

```

> **Wrap-up**: By the end of this section, your code should match [this branch](https://github.com/bitovi/angular-ngrx-chat/tree/test-selectors). You can also compare the [code changes for our solution to this section](https://github.com/bitovi/angular-ngrx-chat/compare/create-selectors...test-selectors) on GitHub or you can use the following command in your terminal:

```
git diff origin/test-selectors
```

###### On this page...

###### Get help

If you need [help](https://discord.gg/J7ejFsZnJ4) with an exercise, please reach out to us on [Discord](https://discord.gg/J7ejFsZnJ4)

If you find a bug, please [create an issue](https://github.com/bitovi/academy/issues/new) or email [contact@bitovi.com](mailto:contact@bitovi.com?Subject=Training%20Suggestion)

## Join the Bitovi Newsletter

 Do you want to receive updates about new Bitovi Academy courses, Bitovi open source projects, and dev community news? If so, please provide your email. We won’t spam you or give it away for any reason!  
*By providing your email you agree to receive communications from Bitovi*

![](https://bitovi.github.io/academy/static/img/close.svg)

```json
{
     "@context": "http://schema.org",
     "@type": "Organization",
     "mainEntityOfPage":{
          "@type":"WebPage",
          "@id":"https://www.bitovi.com/academy/learn-ngrx/test-selectors.html",
          "description": "Learn how to write unit tests for NgRx Selectors. 
"
     },
     "url": "http://bitovi.com",
     "logo": "https://www.bitovi.com/hubfs/bitovi-logo-23-1.svg",
     "image": "https://www.bitovi.com/hubfs/bitovi-logo-x2.png",
     "name": "Bitovi Web App Consulting",
     "alternateName": "Bitovi",
      "naics": "541511",
      "description": "Bitovi is a UX, UI design and front-end JavaScript development consulting company",
     "address": {
          "@type": "PostalAddress",
          "streetAddress": "1134 Pine Tree Lane ",
          "addressLocality": "Libertyville",
          "addressRegion": "IL",
          "addressCountry": "United States",
          "postalCode": "60048"
     },
     "areaServed": {
          "@type": "GeoCircle",
          "geoMidpoint": {
               "@type": "GeoCoordinates",
               "latitude": "41.8781",
               "longitude": "87.6298"
          },
          "geoRadius": "5000 km"
     },
     "telephone": "312-620-0386",
     "email": "contact@bitovi.com",
     "sameAs": [
          "https://www.facebook.com/BitoviLLC/",
          "https://twitter.com/bitovi",
          "https://www.linkedin.com/company/bitovi"
     ]
}
```