英文:
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("Given a config repository", () => {
let target: ConfigRepository;
beforeEach(() => {
target = InMemoryConfigRepository();
});
test("When creating a new config, Then it is persisted properly", 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]);
});
});
that can be applied against an implementation of my interface:
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>;
};
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]]
)(
"Given a config repository (implementation no. %#)",
(configRepositoryConstructor: new () => ConfigRepository) => {
let target: ConfigRepository;
beforeEach(() => {
target = configRepositoryConstructor();
});
test("When creating a new config, Then it is persisted properly", async () => {
// current test implementation
});
}
);
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论