MSSE SENG 5199

Course Materials for the MSSE Web Application Development Course

Testing Angular Apps

Marc Kapke

kapkema@gmail.com


Unit Testing


Jasmine


Core Jasmine Concepts


Suite


Spec


Expectations


Example Expectations

expect(value).toEqual(expected);
expect(value).not.toBe(4);
expect('Hello World').toMatch(/lo /);
expect(value).not.toBeUndefined();
expect(something).toBeTruthy();

Example Jasmine Test:

describe("A suite", function() {
  it("contains spec with an expectation", function() {
    expect(true).toBe(true);
  })
});

Grouping and Nesting Suites

describe('my component', function() {
  describe('does these things', function() {
    it('does a', function() {});
    it('does b', function() {});
  });

  describe('does other things too', function() {
    it('does c', function() {});
    it('does d', function() {});
  });
});

Setup and Teardown


Spies


Spies Example

describe("A spy", function() {
  var foo, bar = null;

  beforeEach(function() {
    foo = {
      setBar: function(value) {
        bar = value;
      }
    };

    spyOn(foo, 'setBar');

    foo.setBar(456, 'another param');
  });

  it("tracks that the spy was called", function() {
    expect(foo.setBar).toHaveBeenCalled();
  });

  it("tracks all the arguments of its calls", function() {
    expect(foo.setBar).toHaveBeenCalledWith(456, 'another param');
  });
});

Spy Responses


Spy Call Checks


Advanced Matching


Advanced Matching Examples

expect({}).toEqual(jasmine.any(Object));
expect({}).toEqual(jasmine.anything());
expect(1).toEqual(jasmine.any(Number));
expect({name: 'Mike', age: 21}).toEqual(jasmine.objectContaining({age:21}));
expect([1,2,3,4]).toEqual(jasmine.arrayContaining([1,4]));

Karma


Karma Config File


Example Karma Config


module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular/cli'],
    plugins: [
      require('karma-jasmine'),
      ...
    ],
    client:{
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    files: [
      { pattern: './src/test.ts', watched: false }
    ],
    preprocessors: {
      './src/test.ts': ['@angular/cli']
    },    
    reporters: config.angularCli && config.angularCli.codeCoverage
              ? ['progress', 'coverage-istanbul']
              : ['progress', 'kjhtml'],
    port: 9876,
    colors: true,
    autoWatch: true,
    browsers: ['Chrome'],
    singleRun: false
  });
};

Test Watcher


Test Watcher Config

config.set({
  ...
  autoWatch: true,
  singleRun: false,
  ...
});

Angular Integration Testing Basics


TestBed


configureTestingModule()

beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ MyComponent ]
    });
  })

TestBed - createComponent


ComponentFixture


detectChanges()


Example Inline Template Test

describe('MyComponent (inline template)', () => {

  let component:    BannerComponent;
  let fixture: ComponentFixture<BannerComponent>;
  let debugElement:      DebugElement;
  let templateElement:      HTMLElement;

  beforeEach(() => {
    TestBed.configureTestingModule({
      declarations: [ MyComponent ], // declare the test component
    });

    fixture = TestBed.createComponent(MyComponent);

    component = fixture.componentInstance; // MyComponent test instance

    // query for the title <h1> by CSS element selector
    debugElement = fixture.debugElement.query(By.css('h1'));
    templateElement = debugElement.nativeElement;
  });

  it('should display original title', () => {
    fixture.detectChanges();
    expect(templateElement.textContent).toContain(component.title);
  });
});