伪造的数据库缺少 x 属性,但这些属性是私有的
Faked database is missing x properties, however those properties are private
我正在尝试为我的代码编写一些测试。我正在使用依赖注入,我正在尝试创建我的数据库的伪造版本,以便在 运行 测试时使用。
我正在使用关键字 implements
来定义我的伪造数据库,但是由于这个伪造的数据库缺少某些属性,我收到了打字稿错误,但是,这些属性是私有的,并且从未在 class
之外使用
这是一个例子:
class Database {
private client: MongoClient;
public async getData(query: string): Promise<{ name: string }> {
return await this.client.db('db').collection('collection').findOne({ name: query });
}
}
class MockDatabase implements Database {
public async getData(query: string): Promise<{ name: string }> {
return {
name: 'Jo'
}
}
}
function makeApp(database: Database) {
console.log(`Here's your app`);
}
const fakeDB = new MockDatabase();
const app = makeApp(fakeDB)
Typescript 在声明 MockDatabase
以及在 makeApp
函数中使用它时都会出错。
Property 'client' is missing in type 'MockDatabase' but required in type 'Database'
我应该如何伪造数据库或类似的其他服务?
A Database
需要有 client
属性,因为 属性 是 private
,这意味着你只能得到一个有效的 Database
来自 Database
构造函数。没有办法用不同的声明来“模拟”Database
,因为 private
properties need to come from the same declaration in order to be compatible. This restriction is important, because private
properties are not completely inaccessible from outside the object; they are accessible from other instances of the same class. See 需要更多信息。
无论如何,与其尝试模拟 Database
,不如考虑创建一个新的 interface
,它只是 Database
的“public 部分”。它看起来像这样:
// manually written out
interface IDatabase {
getData(query: string): Promise<{ name: string }>
}
您可以让编译器为您计算这个,因为 the keyof
operator 只有 returns 对象类型的 public 属性 名称:
// computed
interface IDatabase extends Pick<Database, keyof Database> { }
类型 Pick<Database, keyof Database>
使用 the Pick<T, K>
utility type 到 select 只是 Database
的 public 属性。在这种情况下,它只是 "getData"
,因此计算出的 IDatabase
等同于手动计算出的 IDatabase
。
现在我们将对 Database
的引用更改为 IDatabase
我们只关心 public 部分的任何地方:
class MockDatabase implements IDatabase {
public async getData(query: string): Promise<{ name: string }> {
return {
name: 'Jo'
}
}
}
function makeApp(database: IDatabase) {
console.log(`Here's your app`);
}
const fakeDB = new MockDatabase();
const app = makeApp(fakeDB)
一切都按预期进行。
我正在尝试为我的代码编写一些测试。我正在使用依赖注入,我正在尝试创建我的数据库的伪造版本,以便在 运行 测试时使用。
我正在使用关键字 implements
来定义我的伪造数据库,但是由于这个伪造的数据库缺少某些属性,我收到了打字稿错误,但是,这些属性是私有的,并且从未在 class
这是一个例子:
class Database {
private client: MongoClient;
public async getData(query: string): Promise<{ name: string }> {
return await this.client.db('db').collection('collection').findOne({ name: query });
}
}
class MockDatabase implements Database {
public async getData(query: string): Promise<{ name: string }> {
return {
name: 'Jo'
}
}
}
function makeApp(database: Database) {
console.log(`Here's your app`);
}
const fakeDB = new MockDatabase();
const app = makeApp(fakeDB)
Typescript 在声明 MockDatabase
以及在 makeApp
函数中使用它时都会出错。
Property 'client' is missing in type 'MockDatabase' but required in type 'Database'
我应该如何伪造数据库或类似的其他服务?
A Database
需要有 client
属性,因为 属性 是 private
,这意味着你只能得到一个有效的 Database
来自 Database
构造函数。没有办法用不同的声明来“模拟”Database
,因为 private
properties need to come from the same declaration in order to be compatible. This restriction is important, because private
properties are not completely inaccessible from outside the object; they are accessible from other instances of the same class. See
无论如何,与其尝试模拟 Database
,不如考虑创建一个新的 interface
,它只是 Database
的“public 部分”。它看起来像这样:
// manually written out
interface IDatabase {
getData(query: string): Promise<{ name: string }>
}
您可以让编译器为您计算这个,因为 the keyof
operator 只有 returns 对象类型的 public 属性 名称:
// computed
interface IDatabase extends Pick<Database, keyof Database> { }
类型 Pick<Database, keyof Database>
使用 the Pick<T, K>
utility type 到 select 只是 Database
的 public 属性。在这种情况下,它只是 "getData"
,因此计算出的 IDatabase
等同于手动计算出的 IDatabase
。
现在我们将对 Database
的引用更改为 IDatabase
我们只关心 public 部分的任何地方:
class MockDatabase implements IDatabase {
public async getData(query: string): Promise<{ name: string }> {
return {
name: 'Jo'
}
}
}
function makeApp(database: IDatabase) {
console.log(`Here's your app`);
}
const fakeDB = new MockDatabase();
const app = makeApp(fakeDB)
一切都按预期进行。