gpt4 book ai didi

c# - 编写可测试的 "import data from database"类

转载 作者:搜寻专家 更新时间:2023-10-30 20:32:56 27 4
gpt4 key购买 nike

我的任务是从第 3 方供应商的 SQLite 数据表中提取所有行,根据这些记录创建业务对象,并将新的业务对象发送到另一个类。

伪代码:

var databasePath = "%user profile%\application data\some3rdPartyVendor\vendor.sqlite"
var connection = OpenSqliteConnection(databasePath);
var allGizmoRecords = connection.Query(...);
var businessObjects = TransformIntoBizObjs(allGizmoRecords);
someOtherClass.HandleNewBizObjs(businessObjects);

我已经完成了所有工作。

我的问题是:我怎样才能编写这个类以使其可以进行单元测试?

我应该:

  • 使用存储库模式模拟数据访问
  • 在单元测试中实际提供一个虚拟 SQLite 数据库

或者有什么更好的主意?我正在使用 C#,但这个问题似乎与语言无关。

最佳答案

可以很容易地注入(inject)一个仅供测试的 Sqlite 数据库,将代码重构为如下所示。但是您如何断言结果?业务对象被传递给 someOtherClass。如果您注入(inject)一个 ISomeOtherClass,该类的操作也需要可见。好像有点疼。

public class KillerApp
{
private String databasePath;
private ISomeOtherClass someOtherClass;

public KillerApp(String databasePath, ISomeOtherClass someOtherClass)
{
this.databasePath = databasePath;
this.someOtherClass = someOtherClass;
}

public void DoThatThing()
{
var connection = OpenSqliteConnection(databasePath);
var allGizmoRecords = connection.Query(...);
var businessObjects = TransformIntoBizObjs(allGizmoRecords);
someOtherClass.HandleNewBizObjs(businessObjects);
}
}

[TestClass]
public class When_Doing_That_Thing
{
private const String DatabasePath = /* test path */;
private ISomeOtherClass someOtherClass = new SomeOtherClass();
private KillerApp app;

[TestInitialize]
public void TestInitialize()
{
app = new KillerApp(DatabasePath, someOtherClass);
}

[TestMethod]
public void Should_convert_all_gizmo_records_to_busn_objects()
{
app.DoThatThing();
Assert.AreEqual(someOtherClass.Results, /* however you're confirming */);
}
}

使用 IRepository 会从此类中删除一些代码,从而允许您模拟 IRepository 实现,或伪造一个仅用于测试。

public class KillerApp
{
private IRepository<BusinessObject> repository;
private ISomeOtherClass someOtherClass;

public KillerApp(IRepository<BusinessObject> repository, ISomeOtherClass someOtherClass)
{
this.repository = repository;
this.someOtherClass = someOtherClass;
}

public void DoThatThing()
{
BusinessObject[] entities = repository.FindAll();
someOtherClass.HandleNewBizObjs(entities);
}
}

[TestClass]
public class When_Doing_That_Thing
{
private const String DatabasePath = /* test path */;
private IRepository<BusinessObject> repository;
private ISomeOtherClass someOtherClass = new SomeOtherClass();
private KillerApp app;

[TestInitialize]
public void TestInitialize()
{
repository = new BusinessObjectRepository(DatabasePath);
app = new KillerApp(repository, someOtherClass);
}

[TestMethod]
public void Should_convert_all_gizmo_records_to_busn_objects()
{
app.DoThatThing();
Assert.AreEqual(someOtherClass.Results, /* however you're confirming */);
}
}

但是这样感觉还是挺麻烦的。有两个原因,1) Repository 模式是getting some bad press最近来自 Ayende ,谁对 Repository 略知一二。 2) 你在做什么编写你自己的数据访问!?使用 NHibernateActiveRecord !

[ActiveRecord] /* You define your database schema on the object using attributes */
public BusinessObject
{
[PrimaryKey]
public Int32 Id { get; set; }

[Property]
public String Data { get; set; }

/* more properties */
}

public class KillerApp
{
private ISomeOtherClass someOtherClass;

public KillerApp(ISomeOtherClass someOtherClass)
{
this.someOtherClass = someOtherClass;
}

public void DoThatThing()
{
BusinessObject[] entities = BusinessObject.FindAll() /* built-in ActiveRecord call! */
someOtherClass.HandleNewBizObjs(entities);
}
}

[TestClass]
public class When_Doing_That_Thing : ActiveRecordTest /* setup active record for testing */
{
private ISomeOtherClass someOtherClass = new SomeOtherClass();
private KillerApp app;

[TestInitialize]
public void TestInitialize()
{
app = new KillerApp(someOtherClass);
}

[TestMethod]
public void Should_convert_all_gizmo_records_to_busn_objects()
{
app.DoThatThing();
Assert.AreEqual(someOtherClass.Results, /* however you're confirming */);
}
}

结果是一个更小的类和一个您可以更容易更改的业务对象和数据层。而且您甚至不必模拟数据库调用,您可以配置和初始化 ActiveRecord 以使用测试数据库(甚至在内存中)。

关于c# - 编写可测试的 "import data from database"类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/952682/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com