How to unit test model interfaces in typescript?
Asked Answered
R

3

17
export interface User {
    name: string;
}

How can I unit test the above interface, so Karma could show it in the code coverage report?

I already tried creating the object and assert some properties, but didn't work. The test passes but karma doesn't consider it in the code coverage report.

import { User } from "./user";

describe('User', () => {

    it('test', () => {
        const obj: User = {
            name: "xxx",

        }
        expect(obj.name).toEqual("xxx");
    });

});
Reserve answered 18/4, 2018 at 18:53 Comment(2)
You can't. There is no code to cover here: nothing is executable. And interfaces only exist at compile-time. They don't exist at runtime.Lacerated
I haven't used Karma, but have you tried running tests with karma-typescript? It may take in to account un-accessible code like that. npmjs.com/package/karma-typescriptConferee
L
32

You can't. There is no code to cover here: nothing is executable.

And interfaces only exist at compile-time. They don't exist at runtime.

Lacerated answered 18/4, 2018 at 19:2 Comment(0)
C
4

For future users with a similar question, I've come up with the following system for testing interfaces (which I only use with particularly quirky interfaces, like those I've autogenerated). It's absolutely a workaround, but it does fail my builds if the interface isn't appropriately specified.

First, in the "test", cast an object with the expected fields and types into the interface. For instance,

interface MyInterface = { 
  id: number;
  createTime: Date;
}

test("MyInterface should have appropriate fields and types", () => {
  ({
    id: 3,
    createTime: new Date(),
  } as MyInterface);
})

Then, I added a build step for compiling the TypeScript, which will error if MyInterface is changed.

tsc --noEmit

Again: my tests have no assertions in them, so they're not a real unit test, and this is a workaround. But this process has alerted me to problems a few times, so it serves the purpose.

Cussedness answered 28/8, 2019 at 17:30 Comment(1)
Great idea...works for my needs: protection against unwanted interface changes.Creamery
P
1

My answer elaborates on @JB_Nizet's.

You can't do test coverage for a report, but there are alternatives:

1. Put your interface in a separate file and specify to ignore it when creating a coverage report. For example, I use the istanbul library for the code test coverage report, and it provides for ignoring files. In order for the file to be ignored, it is enough to specify in it:

/* istanbul ignore file */

2. If it is important for you to monitor the compliance of your types and interfaces, you can write tests for them that will be performed during verification, but at the same time do not affect the coverage report. There are many options on the web for how to do this, but I like the way with assigning the tested interface to a variable the most.:

interface IResponse {
  success: boolean;
  message: string;
}

describe('IResponse interface', () => {
  it('should have a boolean property named success', () => {
    const response: IResponse = { success: true, message: 'Test message' };
    expect(response.success).toBeDefined();
    expect(typeof response.success).toBe('boolean');
  });

  it('should have a string property named message', () => {
    const response: IResponse = { success: true, message: 'Test message' };
    expect(response.message).toBeDefined();
    expect(typeof response.message).toBe('string');
  });
});
Presber answered 4/5, 2023 at 2:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.