Is it advisable to reuse encapsulated constants during unit testing and if so, what is the best

Hey there, I'm currently working on a unit test for a function. While the technical details are not crucial, I thought it would be helpful to provide some code snippets for better understanding.
Check out the function below:

export function getSalutations(lang: Salutation = Salutation.default): string[] {
    return SALUTATIONS[lang] || SALUTATIONS.default;
};

export const enum Salutation {
    de,
    es,
    default
};
const SALUTATIONS = {
    de: ['Hr.', 'Fr.'],
    es: ['Sr.', 'Sra.'],
    default: ['Mr.', 'Mrs.', 'Ms.']
};

Here's an example of a unit test scenario:

QUnit.module('getSalutations', (hooks) => {
    QUnit.test('null / default salutations', (assert) => {
        assert.ok(DW.Utils.isEqual(DW.Utils.getSalutations(null), ['Mr.', 'Mrs.', 'Ms.']));
    });
});

I have encountered a dilemma regarding how to approach testing without duplicating code. Ideally, I'd like to reuse the SALUTATIONS object for my tests to avoid redundancy. However, since it is not exported from its current scope, I am unable to access it.

At this point, I see two possible solutions:

  1. Replicate code as mocked data for testing purposes.
  2. Expose encapsulated code solely for unit testing.

Neither option seems ideal to me, so I am reaching out in the hopes that someone can suggest a more optimal solution. Perhaps there are alternative approaches that I haven't considered yet?

Appreciate any insights!

Answer №1

This question may potentially be closed due to subjectivity, but I will provide an answer regardless.

In your code, you should focus on abstractions.

When it comes to testing, your emphasis should be on concrete examples.

For instance, if your test involves checking that the application outputs Hello Mr Smith by default and Hallo Herr Smith for German, these specific strings should be included in your test as they represent tangible expected output examples.

If you use the SALUTATIONS object to generate the strings for your tests, you can make changes without causing any test failures:

const SALUTATIONS = {
    de: ['Hr.', 'Fr.'],
    es: ['Sr.', 'Sra.'],
    default: ['Whatever.', 'I quit.', 'I hate my job.']
};

Answer №2

While some may argue that this question is subjective (as per @Fenton's suggestion), I understand your dilemma as it is a common one in the JS world. My recommendation is to reiterate the values in your test. It is essential to clarify what exactly you are testing, which appears to be the return of values from the getSalutations method. In this case, you can focus on testing three key aspects:

  1. Confirming that an array is returned,
  2. Checking for at least one entry (or more) within the array,
  3. Verifying the presence of specific values in the array.

Therefore, you must determine which of these criteria you wish to test, and if it involves the third one (which essentially includes all three), then repeating the values in your test is imperative. Any addition of new values should prompt updates to your test to account for any potential inclusion of invalid values.

These are just my thoughts on the matter.

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

When incorporating Papaparse with Angular 2, encountering the issue "Identifier 'Papa' is not found" may arise

Currently, I am facing an issue in my project where after deleting and re-installing node_modules to resolve errors, the definition of 'Papa' is missing. As a result, when npm updated the node modules again, Angular 2 is unable to find 'Papa ...

The type 'Observable<HttpEvent<DeviceList>>' cannot be assigned to the type 'Observable<DeviceList>'

// FUNCTION TO RETRIEVE DEVICE LIST fetchDeviceList(): Observable < DeviceList > { this.setToken(); return this.http.get<DeviceList>(this.api_url + '/devices', this.httpOptions1) .retry(2); } I am facing a challenge in this p ...

The item may be undefined and attempting to call a possibly undefined object is not allowed

Hey there! I created this map of functions to filter an object in a JSON file. For each key, I've defined a specific filter function. const filterMap: Map< string, (ticket: Ticket, filter: request) => boolean > = new Map(); filterMap.set ...

Show a few values as a string in Angular using Typescript

I am working with JSON data and I want to know how to display hobbies without including the word "all" in an Angular/TypeScript application. { "Name": "Mustermann1", "Vorname": "Max1", "maennlich& ...

Is it possible to compress an Array comprised of nested Arrays?

I am working on a function that takes in a specific type structure: type Input = [Array<string>, Array<number>, Array<boolean>]; It then transforms and outputs the data in this format: Array<[string, number, boolean]> This essenti ...

What is the process for integrating a JOI validator with a Firebase function?

Is there a way to incorporate JOI validator into Firebase functions as middleware? When calling a Firebase function, it looks something like this: exports.createUserAccount = region("europe-east1").https.onCall(createAccount); // createAccount is ...

Is there a way to correct Typescript's misunderstanding of the interface from a JSON file that has been imported?

The structure of my JSON file is as follows: [ { "keys": [ { "date": "2019-06-25T17:33:39.000Z" } ], "tag": null }, { "keys": [], "tag": "stringvalue" } ] Upon importing the file, Typescript assumes that ke ...

Exploring JSONPath in Cypress

I am currently working on extracting a JSON path for the specific HTML content with the language code DE Below is an example of the JSON data: { "name": "Name", "text": "", "html": "HTML content" ...

Aurelia - Struggling to integrate CssAnimator with a basic message div

Currently, I am utilizing Typescript and referencing an informative blog post by Mikhail Shilkov. Even though I am implementing Typescript, the blog post revolves around Javascript. This has led me to ponder whether this difference is the root cause of th ...

Guide to creating varying component sizes using ReactJS and Styled Components

Is it possible to add variation to my button based on the prop 'size' being set to either 'small' or 'medium'? interface Props { size?: 'medium' | 'small'; } How can I adjust the size of the component us ...

Different kinds of functions can take an optional property name as an argument and either return the value of that property in an object or the entire object itself

In need of a function that accepts an optional parameter propName, which must be a key belonging to SOME_OBJECT. The function should return the value of propName if it is provided, or else return the entire OBJECT: Here's the code snippet: type SOME_ ...

Sharing variables between Angular 2 components: An in-depth guide

Looking for a way to change a variable in a group of child components, I have this component for an editable form control that toggles between view states import { Component, Input, ElementRef, ViewChild, Renderer, forwardRef, ...

Generic Typescript Placeholder Design

Imagine you have the following data: const dataA = { name: "John", age: 25, attributes: {specificA: "hello", specificA2: 14, nonspecific:"Well"}, } const dataB = { name: "Lisa", age: 38, attributes: {spe ...

Tips for correctly specifying the types when developing a wrapper hook for useQuery

I've encountered some difficulties while migrating my current react project to typescript, specifically with the useQuery wrappers that are already established. During the migration process, I came across this specific file: import { UseQueryOptions, ...

Avoiding type errors in d3 v5 axis by using Typescript

I am new to TypeScript and I have some code that is functioning perfectly. I believe if I define a type somewhere, d3's generics will come into play? Within my code, I have an xAxis and a yAxis. Both are the same, but D3 seems to have an issue with t ...

Troubleshooting a database update issue within an Angular and NestJS application

Hey there, I am a newcomer to both Angular and NestJS. I'm currently facing an issue with updating a specific row in my database through the frontend. While I can easily insert new data, updating seems to be problematic. Here's how my files are s ...

What is causing the issue where search query parameters are not recognizing the initially selected option?

Hey, I'm having an issue with searchParams. The problem is that when I apply filters like "Breakfast, Lunch, Dinner", the first chosen option isn't showing up in the URL bar. For example, if I choose breakfast nothing happens, but if I choose lun ...

Is it necessary for vertex labels to be distinct within a graph?

I am currently developing a browser-based application that allows users to create graphs, manipulate them, and run algorithms on them. At the moment, each vertex is represented by a unique positive integer. However, I am considering implementing labeled ve ...

What is the process for retrieving the GitHub username in the GitHub OAuth Next.js sign-in callback in order to store it in a database?

1. Detail the issue I am facing a challenge while developing a Full Stack Website using Next.js and Typescript. Specifically, I am having difficulty persisting the Github Username in the database when a user signs in via Github OAuth. Should I consider st ...

Exploring the power of EJS with conditional logic

Can someone help me figure out why EJS is not evaluating to the else branch in my code? I'm using EJS version 3.1.5 with express version 4.17.1 and typescript. ReferenceError: /home/pauld/tscript/dist/views/index.ejs:12 10| </head> 11| & ...