---
description: >-
  In this section we will start to see the benefit of using redux in making out
  testing simpler as we separate out the concerns of updating state with those
  of rendering views in a component.
---

# 14. Test reducer

## 1. Fix broken EventComponent test

We need to fix our broken tests every time we add a new dependency to a component or thing under test it will need to be provided to the tests environment.

* Fix the test by providing a fake `Store` . There are more syntactically simpler ways to deal with this type of faking boiler plate but for now I would like to make it verbose and explicit what we are doing in these tests.

{% code title="src/app/event/container/event/event.component.spec.ts" %}
```typescript
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { of } from 'rxjs';
import { Store } from '@ngrx/store';
import { NO_ERRORS_SCHEMA } from '@angular/compiler/src/core';
import { HttpClient } from '@angular/common/http';

import { EventComponent } from './event.component';
import { EventService } from '../../services/event.service';

describe('EventComponent', () => {
  let component: EventComponent;
  let fixture: ComponentFixture<EventComponent>;
  let service: EventService;
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      providers: [
        { provide: HttpClient, useValue: null },
        {
          provide: EventService,
          useValue: {
            getAttendees: () => {}
          }
        },
        {
          provide: Store,
          useValue: {
            pipe: () => {}
          }
        }
      ],
      declarations: [EventComponent],
      schemas: [NO_ERRORS_SCHEMA]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(EventComponent);
    component = fixture.componentInstance;
    service = TestBed.get(EventService);
    fixture.detectChanges();
  });

  it('should create', () => {
    expect(component).toBeTruthy();
  });

  it('should have a list of attendees set', () => {
    const fakeAttendees = [{ name: 'FAKE_NAME', attending: false, guests: 0 }];

    jest
      .spyOn(service, 'getAttendees')
      .mockImplementation(() => of(fakeAttendees));

    component.ngOnInit();

    component.attendees$.subscribe(attendees => {
      expect(attendees).toEqual(fakeAttendees);
    });
  });
});

```
{% endcode %}

## 2. Test a reducer

Reducers are so simple to test as they are pure functions. We just need to call the reducer function and pass in a fake piece of state and an action and then check the new state slice returns.

* Create a spinner.reducer.spec.ts file to the state folder.
* Add a test to check we return the `state` passed in if the cases do not match any action types.

{% code title="src/app/state/spinner/reducer.spec.ts" %}
```typescript
import { reducer } from './spinner.reducer';

describe('Reducer: Spinner', () => {
  it('should have initial state of isOn false', () => {
    const expected = { isOn: false };
    const action = { type: 'foo' } as any;
    expect(reducer(undefined, action)).toEqual(expected);
  });
});
```
{% endcode %}

* Add another test to check we return new `state` with the isOn flag set to true when we pass in a `startSpinner` action.

{% code title="src/app/state/spinner/reducer.spec.ts" %}
```typescript
import { reducer } from './spinner.reducer';

describe('Reducer: Spinner', () => {
  it('should have initial state of isOn false', () => {
    const expected = { isOn: false };
    const action = { type: 'foo' } as any;
    expect(reducer(undefined, action)).toEqual(expected);
  });

  it('should have a isOn set to true', () => {
    const state = { isOn: false };
    const action = { type: 'startSpinner' };
    const expected = { isOn: true };
    expect(reducer(state, action)).toEqual(expected);
  });
});
```
{% endcode %}

## StackBlitz Link

{% embed url="https://stackblitz.com/github/duncanhunter/angular-and-ngrx-demo-app/tree/14-test-reducer" %}
Web Link: Link to the demo app running in StackBlitz
{% endembed %}
