Confirm that the dependency has been invoked using Sinon

I am currently working on testing whether a dependency has been called or not.

Here is an example of my code:

export default class vehicle {
private builder: CarBuilder;

constructor() {
  this.builder = CreateCar(); <- factory return fake data
}

createBmw(model) {
  return this.builder.validate(model); <- test this line has been called
}

This is what my test looks like:

it("should verify that the createBmw method calls validate", () => {
  //Am I doing this correctly?
  const carBuilder = new carBuilder();
  const builder = sinon.stub(carBuilder, "validate");

  const sut = new vehicle();
  sut.createBmw("5 series");

  expect(builder).to.be.called;
});

Answer №1

Sinon is unable to stub standalone functions such as the CreateCar factory function in this scenario. Therefore, it is recommended to utilize Link Seams for this purpose. To achieve this, we will employ proxyquire to create our seams.

For example:

vehicle.ts:

import { CarBuilder, CreateCar } from './builders/carBuilder';

export default class Vehicle {
  private builder: CarBuilder;

  constructor() {
    this.builder = CreateCar();
  }

  createBmw(model) {
    return this.builder.validate(model);
  }
}

builders/carBuilder.ts:

export interface CarBuilder {
  validate(model): void;
}

export function CreateCar(): CarBuilder {
  return { validate(model) {} };
}

vehicle.test.ts:

import proxyquire from 'proxyquire';
import sinon from 'sinon';

describe('68197110', () => {
  it('should pass', () => {
    const carStub = { validate: sinon.stub() };
    const CreateCarStub = sinon.stub().returns(carStub);
    const Vehicle = proxyquire('./vehicle', {
      './builders/carBuilder': {
        CreateCar: CreateCarStub,
      },
    }).default;
    const sut = new Vehicle();
    sut.createBmw('5 series');
    sinon.assert.calledWithExactly(carStub.validate, '5 series');
  });
});

Unit test results:

  68197110
    ✓ should pass (1481ms)


  1 passing (1s)

-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   83.33 |      100 |      50 |   83.33 |                   
 68197110          |     100 |      100 |     100 |     100 |                   
  vehicle.ts       |     100 |      100 |     100 |     100 |                   
 68197110/builders |      50 |      100 |        0|      50 |                   
  carBuilder.ts    |      50 |      100 |        0|      50 | 6                 
-------------------|---------|----------|---------|---------|-------------------

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

Processing a list in Angular using Observables

In my Angular12 application, I am fetching data from a Firebase Realtime DB using AngularFire. To streamline my code and ensure consistency, I have implemented a DAO service to preprocess the retrieved data (e.g., converting string dates to Date objects). ...

Enhance Tuple in Angular Component Properties

When using React, state variables can be created like this: const SomeComponent = ({ someProp }) => { const [value, setValue] = useState<boolean>(false); } I wonder if there is a similar way to achieve the spread of a tuple within an Angular co ...

Make sure to verify the optional parameter before using it in your code

Is it possible for TypeScript compiler to detect errors in code such as this, with certain tsconfig rules in place? function buildName(firstName: string, lastName?: string) { return firstName + " " + lastName; } I believe that if there is no c ...

The index.ngfactory.ts file threw an unexpected token error, indicating that an appropriate loader may be necessary to handle this specific file

I've spent several hours trying to troubleshoot this persistent error, exhausting all online resources for solutions. The issue arises consistently with every module of Angular Material only during the build process using --env.prod. The webpack confi ...

When selecting a different file after initially choosing one, the Javascript file upload event will return e.target as null

Currently, I have implemented file uploading using <input>. However, when attempting to change the file after already selecting one, the website crashes and states that event.target is null. <Button label="Upload S3 File"> <input ...

Simple steps to transform the "inputs" syntax into the "@Input" property decorator

There's this code snippet that I need to modify: @Component({ selector: 'control-messages', inputs: ['controlName: control'], template: `<div *ngIf="errorMessage !== null">{{errorMessage}}</div>` }) Is the ...

Exploring Vue 3.3: Understanding Generics and Dynamic Properties

I'm currently diving into the generics feature in vue 3.3 and I've been pondering about defining the type of an incoming prop based on another prop value. This is my current component structure: export interface OptionProps { id: string | numb ...

Addressing the reactivity issue when incorporating basic markdown directive into vuejs

In an effort to reduce dependency on vue-i18n formatting, I decided to create a simple Markdown formatter directive that only implements bold, emphasize, and strike-through styles. The current implementation of the directive is as follows: import _Vue ...

Refresh the mapbox source features in real-time

Currently, I am mapping out orders on a map with layers and symbols that have different statuses. When the status of an order changes, I want to update the color of the symbol accordingly. The layer configuration looks like this: map.addLayer({ id: &q ...

Issue encountered when attempting to develop a countdown timer using Typescript

I am currently working on a countdown timer using Typescript that includes setting an alarm. I have managed to receive input from the time attribute, converted it using .getTime(), subtracted the current .getTime(), and displayed the result in the consol ...

The error code TS2554 is triggered when the function expects between 1 to 2 arguments, but receives

When attempting to include { useHash: true } in RouterModule.forRoot, I encountered the following error. How can I add additional arguments? @NgModule({ imports: [RouterModule.forRoot( appRoutes, { enableTracing: true }, // <-- for debugging ...

An error occurred while running React, Next.js, and Type Script: Unhandled Runtime Error - TypeError: Unable to access 'value' property of undefined

I have been working on a multi-page form and using the antd package to add some styling to it. On the main page of the form, I implemented the following code (making sure I imported everything required). export class CreateNewContract extends Component ...

Extending Vue components with TypeScript for enhanced styling features

Exploring Vuejs with TypeScript components has been an educational journey for me. While I found using class-based components quite intuitive, I've encountered errors when trying to use the Vue.extend({}) approach. Are there any resources such as arti ...

Bring in a function by its name from the ts-nameof package that is not declared in the d.ts export

Recently, I came across a captivating package that caught my interest and I would love to incorporate it into my TypeScript application: https://github.com/dsherret/ts-nameof However, upon attempting to import the nameof function, I realized it was not be ...

Encountering an issue with the message: "Property 'ref' is not available on the type 'IntrinsicAttributes'."

Having trouble implementing a link in React and TypeScript that scrolls to the correct component after clicking? I'm using the useRef Hook, but encountering an error: Type '{ ref: MutableRefObject<HTMLDivElement | null>; }' is not assi ...

Typescript iterative declaration merging

My current project involves creating a redux-like library using TypeScript. Here is an example of the basic action structure: interface ActionBase { type: string; payload: any; } To customize actions for different types, I extend the base interface. ...

Need help with TypeScript syntax for concatenating strings?

Can you explain the functionality of this TypeScript syntax? export interface Config { readonly name: string readonly buildPath: (data?: Data) => string readonly group: string } export interface Data { id: number account: string group: 'a&a ...

When trying to update a form field, the result may be an

Below is the code for my component: this.participantForm = this.fb.group({ occupation: [null], consent : new FormGroup({ consentBy: new FormControl(''), consentDate: new FormControl(new Date()) }) }) This is th ...

Can you provide guidance on how to specifically specify the type for the generics in this TypeScript function?

I've been diving into TypeScript and experimenting with mapped types to create a function that restricts users from extracting values off an object unless the keys exist. Take a look at the code below: const obj = { a: 1, b: 2, c: 3 } fun ...

Converting a TypeScript array into a generic array of a specific class

I am attempting to convert a JSON source array with all string values into another array of typed objects, but I keep encountering errors. How can I correct this code properly? Thank you. Error 1: There is an issue with converting type '({ Id: string ...