Experimenting with a file system library function using Jest and Typescript alongside a placeholder function

When attempting to test a library function that uses the fs module, I received assistance in this question on Stack Overflow. The feedback suggested avoiding mocks for better testing, an approach I agreed with @unional.

I am now facing a similar challenge with the accessSync method, as it requires some modifications for proper testing.

After implementing the suggestions from @unional, here is my updated code:

import fs from 'fs';
export function AccessFileSync(PathAndFileName: string): boolean {
    if (!PathAndFileName) {
        throw new Error('Missing File Name');
    }
    try {
        AccessFileSync.fs.accessSync(PathAndFileName, fs.constants.F_OK | fs.constants.R_OK);
    } catch {
        return false;
    }
    return true;
}
AccessFileSync.fs = fs;

To test this function, I would follow these steps:

describe('Return Mock data to test the function', () => {
    it('should return the test data', () => {
        // mock function
        AccessFileSync.fs = {
            accessSync: () => { return true; }
        };

        const AccessAllowed: boolean = AccessFileSync('test-path');      // Non-existent file due to mock
        expect(AccessFileSync.fs.accessSync).toHaveBeenCalled();
        expect(AccessAllowed).toBeTruthy();
    });
});

While the initial test works, subsequent tests fail to obtain the expected results when changing parameters. For example:

describe('Return Mock data to test the function', () => {
    it('should return the test data', () => {
        // mock function
        AccessFileSync.fs = {
            accessSync: () => { return false; }
        };

        const AccessAllowed: boolean = AccessFileSync('test-path');      // Non-existent file due to mock
        expect(AccessFileSync.fs.accessSync).toHaveBeenCalled();
        expect(AccessAllowed).toBeFalsy();  // Fails to match expectation
    });
});

Additionally, I aim to address tslint warnings regarding the use of "as any" and prefer the notation "Variable:type" instead.

Answer №1

Your function always returns true:

import fs from 'fs';
export function AccessFileSync(PathAndFileName: string): boolean {
  if (PathAndFileName === undefined || PathAndFileName === null || PathAndFileName.length === 0) {
    throw new Error('Missing File Name');
  }
  try {
    AccessFileSync.fs.accessSync(PathAndFileName, fs.constants.F_OK | fs.constants.R_OK);
  }
  catch {
    return false; // here
  }
  return true;
}
AccessFileSync.fs = fs;

To mimic the behavior, your test needs to throw an error as well.

describe('Mocking data to test the function', () => {
  it('should simulate the error case', () => {
    // mocking function
    AccessFileSync.fs = {
      accessSync: () => { throw new Error('try to mimic the actual error') }
    };

    const AccessAllowed: boolean = AccessFileSync('test-path');
    expect(AccessAllowed).toBeFalsy(); 
  });
});

To address the linting issue, you have two options.

The first option is type assertion, which allows you to cast variables but may not be recommended in all scenarios.

The second way involves Interface Segregation Principle to request only what you need from a type/interface.

AccessFileSync.fs = fs as Pick<typeof fs, 'accessSync'>

This approach is more precise but can be more tedious to implement. Hopefully, future advancements in control flow analysis will automate this process.

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

An error occurs in TypeScript when attempting to reduce a loop on an array

My array consists of objects structured like this type AnyType = { name: 'A' | 'B' | 'C'; isAny:boolean; }; const myArray :AnyType[] =[ {name:'A',isAny:true}, {name:'B',isAny:false}, ] I am trying ...

Implementing a feature in ReactJS that allows users to upload multiple images in base64 format

I'm trying to develop an image uploader using base64 and I want the output as an array. However, I am encountering an issue where the array is coming out empty!. I suspect it might be due to an asynchronous problem. Any tips on how to incorporate asyn ...

How to create a manual mock for @material-ui withStyles in React using Jest

I have been experimenting with creating manual mocks for the @material-ui/core/styles module, specifically targeting the HOC known as withStyles. Initially, using an inline mock with jest.mock function worked flawlessly. However, when attempting to reloca ...

Error TS2304: Unable to locate the word 'InputEvent'

While exploring the topic of whether TypeScript has type definitions for InputEvent, I experimented with using @types/dom-inputevent in my Angular 7 project. However, I kept encountering the error TS2304: Cannot find name 'InputEvent' whenever I ...

Angular 2 form with ng2-bootstrap modal component reset functionality

I have implemented ng2-bs3-modal in my Angular 2 application. I am now looking for a way to clear all form fields when the close button is clicked. Can anyone suggest the best and easiest way to achieve this? html <button type="button" class="btn-u ...

Has anyone tried integrating Reveal JS with Angular 8?

Encountering a problem with the integration of Reveal JS in an Angular component. Despite being initialized after DOM processing, it is not displaying anything. What is the appropriate time to initialize the reveal library? Is there a way to incorporate ...

Analyze the information presented in an HTML table and determine the correct response in a Q&A quiz application

I need to compare each row with a specific row and highlight the border accordingly: <table *ngFor="let Question from Questions| paginate: { itemsPerPage: 1, currentPage: p }"> <tr><td>emp.question</td></tr> <tr> ...

The React component continuously refreshes whenever the screen is resized or a different tab is opened

I've encountered a bizarre issue on my portfolio site where a diagonal circle is generated every few seconds. The problem arises when I minimize the window or switch tabs, and upon returning, multiple circles populate the screen simultaneously. This b ...

Looking to arrange an object by the value of a nested object in Typescript/Angular?

I'm currently developing an Angular 9 application focused on covid-19 cases, and I need to arrange my objects by the value of nested objects. Here is the dataset that I want to organize alphabetically based on the 'state' field values: stat ...

Encountering Thumbnail Type Error While Implementing Swiper in Next.js

When trying to integrate Swiper with Next.js, I ran into an issue concerning thumbnails. "onSwiper={setThumbsSwiper}" This line is causing a TypeScript error: swiper-react.d.ts(23, 3): The expected type comes from property 'onSwiper' w ...

How to Send Data with NodeJS by Utilizing the Finish Event

Is there a way to retrieve the JSON data sent during the nodejs finish event? This is how I send the JSON data: oResponse.json({ version: "1.0.0", author: "Someone", contributors: "also Someone" }); I would like ...

Saving many-to-many relationships with entities that are already saved in TypeORM

As a beginner in Typeorm, I have been working on a web page with Angular + Typeorm for the past few weeks. Despite my efforts to resolve this issue by myself and researching previously asked questions here on Stackoverflow, I have unfortunately been unable ...

Display a dynamic array within an Angular2 view

I have a dynamic array that I need to display in the view of a component whenever items are added or removed from it. The array is displayed using the ngOnInit() method in my App Component (ts): import { Component, OnInit } from '@angular/core' ...

Steps for Properly Defining Next.js getServerSideProps as a Function Declaration

I've been working on implementing getServerSideProps (additional information available here, and detailed API documentation here), but my challenge lies in utilizing it as a function declaration instead of an expression. Despite searching for relevant ...

The specified class is not found in the type 'ILineOptions' for fabricjs

Attempting to incorporate the solution provided in this answer for typescript, , regarding creating a Line. The code snippet from the answer includes the following options: var line = new fabric.Line(points, { strokeWidth: 2, fill: '#999999', ...

How do I add a new module to an existing one using Angular-CLI?

After generating modules: $ ng generate module myTestModule installing module create src/app/my-test-module/my-test-module.module.ts $ ng generate module myTestModule2 installing module create src/app/my-test-module2/my-test-module2.module.ts I ha ...

Using Typescript to create an interface that extends another interface and includes nested properties

Here is an example of an interface I am working with: export interface Module { name: string; data: any; structure: { icon: string; label: string; ... } } I am looking to extend this interface by adding new properties to the 'str ...

Issue with TypeScript: Declaring type for objects in an array using .map

I'm having trouble assigning types to the Item object that is being returned from unitedStates.map((item: Item) => {}. Despite my efforts, I am unable to correctly define the types. Although I have specified the unitedStates array of objects as un ...

Is your React conditional rendering malfunctioning due to state issues?

I am attempting to create a component that will only be displayed after clicking on a search button. Below is the current code that I have: Update After making some changes, I am now encountering this error: Error: ERROR in /home/holborn/Documents/Work ...

What is the recommended data type to assign to the `CardElement` when using the `@stripe/react-stripe-js` package in TypeScript?

I'm struggling to determine the correct type to use for this import: import { CardElement } from '@stripe/react-stripe-js'; I have successfully used the types Stripe, StripeElements, and CreateTokenCardData for the stripe and elements props ...