Angular
  • Angular learning
  • Angular
    • Change Detection
      • Angular Change Detection Strategies
      • Understanding Change Detection Strategy in Angular
    • Angular Components Overview
      • Lifecycle hooks
      • View encapsulation
    • Text interpolation
    • Pipes
    • ARIA
    • Event binding
    • Directives
    • Dependency injection in Angular
    • Difference between Template-Driven and Reactive Forms
    • Guards
    • Resolvers
      • Resolver example
  • Memory management in Angular applications
  • Renderer2
  • Angular test
    • Testing
      • The different types of tests
      • Some testing best practices
      • Angular Service Testing in Depth
        • About Jasmine
        • Jasmine - Test suites
        • Implementation of First Jasmine Specfication
        • spyOn() & jasmine.createSpyObj()
        • beforeEach()
        • Testing services
        • Disabled and Focused Tests
        • flush
        • HttpTestingController
        • Sample code
      • Angular Component Testing in Depth
        • Intro to Angular Component testing
        • DOM interaction
        • Trigger Change Detection
        • Test Card List Test Suite Conclusion
        • Window.requestAnimationFrame()
        • Asynchronous Work (Jasmine)
        • Cooperative asynchronous JavaScript: Timeouts and intervals
        • FakeAsync - Asynchronous Work (Jasmine) part 2
        • tick()
        • Sample codes
      • Testing Promised-based code-intro Microtasks
        • Microtasks
        • Micro-tasks within an event loop (Summary)
        • Macro-tasks within an event loop (Summary)
        • Test promised Microtasks (code)
      • Using fakeAsync to test Async Observables
      • Cypress.io
        • Create our first e2e test
      • Angular CLI code coverage and deployment in prod mode.
      • Travis CI
  • Angular best practices
    • Angular best practices
      • Security
      • Accessibility in Angular
      • Keeping your Angular projects up-to-date
    • Bootstrapping an Angular Application
      • Understanding the File Structure
      • Bootstrapping Providers
    • Components in Angular
      • Creating Components
      • Application Structure with Components
        • Accessing Child Components from Template
        • Using Two-Way Data Binding
        • Responding to Component Events
        • Passing Data into a Component
      • Projection
      • Structuring Applications with Components
      • Using Other Components
  • Reactive extensions
    • RxJS
      • RxJS Operators
      • of
      • Observable
      • async pipe (Angular)
      • Interval
      • fromEvent
      • Pipe
      • Map
      • Tap
      • ShareReplay
      • Concat
      • ConcatMap
      • Merge
      • MergeMap
      • ExhaustMap
      • fromEvent
      • DebounceTime
        • Type Ahead
      • Distinct Until Changed
      • SwitchMap
      • CatchError
      • Finalize
      • RetryWhen
      • DelayWhen
      • ForkJoin
      • First
      • Interview Questions
      • Zip
  • NgRx
    • What's NgRx
      • Actions
      • Reducers
      • Selectors
      • 🙅‍♂️Authentication guard with NgRX
      • @ngrx/effects
        • Side-Effect refresh survivor
  • Interview Q&A
    • Angular Unit Testing Interview Questions
    • Angular Questions And Answers
  • Angular Advanced
    • Setting up our environment
      • Understanding Accessors (TS)
      • The host & ::ng-deep Pseudo Selector
Powered by GitBook
On this page
  • spyOn()
  • jasmine.createSpyObj()
  • What's the difference between spyOn and jasmine.createSpyObj

Was this helpful?

  1. Angular test
  2. Testing
  3. Angular Service Testing in Depth

spyOn() & jasmine.createSpyObj()

PreviousImplementation of First Jasmine SpecficationNextbeforeEach()

Last updated 4 years ago

Was this helpful?

spyOn()

Jasmine has test double functions called spies. A spy can stub any function and tracks calls to it and all arguments. A spy only exists in the describe or it block in which it is defined, and will be removed after each spec. There are special matchers for interacting with spies. This syntax has changed for Jasmine 2.0. The toHaveBeenCalled matcher will return true if the spy was called. The toHaveBeenCalledWith matcher will return true if the argument list matches any of the recorded calls to the spy.

In our component we have the following method:

add(n1: number, n2: number) {
    this.logger.log("Addition operation called");
    return n1 + n2;
}

And our spec code we will run the following the code to verify if the this.logger.log is being called only once.

it('should add two numbers', () => {
    const logger = new LoggerService(); // Here we create a new instance of logger service
    spyOn(logger, 'log');
    const calculator = new CalculatorService(logger);
    const result = calculator.add(2, 2);
    expect(result).toBe(4); // First exepct
    
    // Validate how many times the logger is being called
    expect(logger.log).toHaveBeenCalledTimes(1); // Check if the function is being called only once
});

However, if we modify our code to make it fail we can double call the method.

this.logger.log("Addition operation called");
this.logger.log("Addition operation called 2cd");

And here is the result of calling twice the same function:

jasmine.createSpyObj()

it('should add two numbers', () => {
    // Implementing Jasmine Create Spy Object
    const logger = jasmine.createSpyObj('LoggerService', ['log']);
    
    const calculator = new CalculatorService(logger);
    const result = calculator.add(2, 2);
    expect(result).toBe(4); // First exepct
    
    // Validate how many times the logger is being called
    // Check if the function is being called only once
    expect(logger.log).toHaveBeenCalledTimes(1);
});

When there is not a function to spy on, jasmine.createSpy can create a "bare" spy. This spy acts as any other spy - tracking calls, arguments, etc. But there is no implementation behind it. Spies are JavaScript objects and can be used as such.

What's the difference between spyOn and jasmine.createSpyObj

The difference is that you should have a method on the object with spyOn

const o = { some(): { console.log('spied') } };
spyOn(o, 'some');

while the mock method is created for your with createSpy():

const o = {};
o.some = jasmine.createSpy('some');

The advantage of the spyOn is that you can call the original method

spyOn(o, 'some').and.callThrough();
o.some(); // logs 'spied'

's method is useful when you do not have any function to spy upon or when the call to the original function would inflict a lag in time (especially if it involves HTTP requests) or has other dependencies which may not be available in the current context.

Like , it also tracks calls and arguments, but without any real implementation. But unlike , the method to be spied upon need not exist at all.

Jasmine
createSpy()
spyOn()
spyOn()