如何重复使用 Jest 测试来测试相同接口的多个实现?

huangapple go评论63阅读模式
英文:

How to reuse a jest test for multiple impementations of the same interface?

问题

我有一个测试:

describe("给定配置存储库", () => {
    let target: ConfigRepository;

    beforeEach(() => {
        target = InMemoryConfigRepository();
    });

    test("当创建新配置时,它会被正确地持久化", async () => {
        const key = "key";
        const namespace = "namespace";
        const result = await target.upsert({
            key,
            namespace,
            value: "value",
            teamId: "teamId",
        })();
        const configs = await target.findAll()();

        expect(result._tag).toEqual("Right");
        expect(configs.length).toBe(1);
        expect(configs.map((c) => c.key)).toEqual([key]);
    });
});

可以应用于接口的实现:

export type ConfigRepository = {
    get: <T extends RequiredJsonObject>(
        props: ConfigurationProperties<T>
    ) => TE.TaskEither<DatabaseError | MissingConfigError, ConfigEntity[]>;
    findAll(): T.Task<ConfigEntity[]>;
    upsert: (
        config: UnsavedConfig
    ) => TE.TaskEither<DatabaseError, ConfigEntity>;
};

我的问题是我不清楚如何将这个测试应用于同一接口的不同实现。如何测试PrismaConfigRepository并使用相同的测试?

英文:

I have a test:

describe(&quot;Given a config repository&quot;, () =&gt; {
    let target: ConfigRepository;

    beforeEach(() =&gt; {
        target = InMemoryConfigRepository();
    });

    test(&quot;When creating a new config, Then it is persisted properly&quot;, async () =&gt; {
        const key = &quot;key&quot;;
        const namespace = &quot;namespace&quot;;
        const result = await target.upsert({
            key,
            namespace,
            value: &quot;value&quot;,
            teamId: &quot;teamId&quot;,
        })();
        const configs = await target.findAll()();

        expect(result._tag).toEqual(&quot;Right&quot;);
        expect(configs.length).toBe(1);
        expect(configs.map((c) =&gt; c.key)).toEqual([key]);
    });
});

that can be applied against an implementation of my interface:

export type ConfigRepository = {
    get: &lt;T extends RequiredJsonObject&gt;(
        props: ConfigurationProperties&lt;T&gt;
    ) =&gt; TE.TaskEither&lt;DatabaseError | MissingConfigError, ConfigEntity[]&gt;;
    findAll(): T.Task&lt;ConfigEntity[]&gt;;
    upsert: (
        config: UnsavedConfig
    ) =&gt; TE.TaskEither&lt;DatabaseError, ConfigEntity&gt;;
};

My problem is that I don't see a clear way of applying this to different implementations of the same interface. How can I test say a PrismaConfigRepository with the same test?

答案1

得分: 1

你可能想要做的是所谓的参数化测试。实现这个的一种方法是使用 .each。然后的思路是将实现ConfigRepository接口的每个类的构造函数作为参数传递,并在beforeEach中使用构造函数构建实例(而不是始终实例化InMemoryConfigRepository)。

大致草图如下:

describe.each(
   [[InMemoryConfigRepository],[PrismaConfigRepository]]
)(
   "给定一个配置存储库(实现编号 %#)",
   (configRepositoryConstructor: new () => ConfigRepository) => {
        let target: ConfigRepository;

        beforeEach(() => {
            target = configRepositoryConstructor();
        });

        test("创建新配置时,它会被正确持久化", async () => {
           // 当前测试实现
        });
   }
);
英文:

You probably want to to whats called a Parameterized Test. One way to implement this is to use .each. The idea is then to pass the constructor of each of your classes implementing the ConfigRepository interface as a parameter, and constructing the instances using the constructor in beforeEach (rather than always instanciating an InMemoryConfigRepository).

Rough sketch of what this could look like:

describe.each(
   [[InMemoryConfigRepository],[PrismaConfigRepository]]
)(
   &quot;Given a config repository (implementation no. %#)&quot;, 
   (configRepositoryConstructor: new () =&gt; ConfigRepository) =&gt; {
        let target: ConfigRepository;

        beforeEach(() =&gt; {
            target = configRepositoryConstructor();
        });

        test(&quot;When creating a new config, Then it is persisted properly&quot;, async () =&gt; {
           // current test implementation
        });
   }
);

huangapple
  • 本文由 发表于 2023年6月19日 18:56:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/76505962.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定