Search code examples
typescriptunit-testingmixinsdeno

Mixin class in Typescript cannot be mocked by Rhum


Hello community I have this code which fails on the last line. Once it is commented out is is passing through as expected. The problem is when mocking the mixin class.

Have somebody any thoughts, recommendation or ideas how to deal with this problem?

I'm running this by:

  • Deno 1.19.3
  • Typescript 4.5.2

Thank you.

import { Rhum } from "https://deno.land/x/[email protected]/mod.ts";
import { assertInstanceOf } from "https://deno.land/[email protected]/testing/asserts.ts";

export interface IGame {}

export class NullGame implements IGame {}

function WithGameProperty() {
    return <T extends new (...args: any[]) => any>(GameProperty: T) => {
        return class extends GameProperty {
            private game: IGame = new NullGame();

            public set Game(game: IGame) {
                this.game = game;
            }

            public get Game() {
                return this.game;
            }
        };
    };
}

const PlayersEngine = WithGameProperty()(
    class PlayersEngine {
        onNextGenerationReady(listener: () => void): void {
        // add listener to react on an event
        }

        prepareNextGeneration(): void {
        // do some stuff and trigger an event
        }
    },
);

const pe = new PlayersEngine();

pe.Game = new NullGame();

assertInstanceOf(pe.Game, NullGame);

Rhum.mock(NullGame).create();
Rhum.mock(PlayersEngine).create();

Solution

  • for reference, i'm one of the maintainers of Rhum.

    The issue lies with Rhum's internal code, our logic that gets properties, doesn't work with getters and setters. I've toyed around with this and managed to get a working fix, so it isn't your code at all.

    For example:

    let desc = Object.getOwnPropertyDescriptor(original, property);
    if (desc === undefined) {
      // property is a getter or setter
      desc = Object.getOwnPropertyDescriptor(this.constructor_fn.prototype, property)
    }
    // We can now use `desc.value`
    

    I'll be adding a fix for this and a test case, and will release a new patch version tonight, so keep an eye out on the releases :)