如何在 NUnit 中编写集成测试?
How to write an integration test in NUnit?
我们是两个正在写学士论文的学生,我们开发了一个 Windows 应用程序,它应该能够在各种沟通过程中帮助餐厅。从根本上说,它应该能够从客人发送给它的那一刻起就显示有关订单的信息。
我们在开发过程中省略了测试,但现在决定编写单元测试。尽管如此,我们发现我们现在可以写入系统的最合适的测试是集成测试,因为我们 类 中的所有方法都通过 LINQ to SQL 绑定到 SQL 存储过程.我们知道使用存根来伪造对数据库的依赖性,但是当我们的数据库已经与所有功能一起实现时,我们认为将几种方法作为集成测试一起测试会给我们带来更多价值。
如以下代码所示,我们已尝试遵循单元测试的指南,但这是编写集成测试的正确方法吗?
[Test]
public void SendTotalOrder_SendAllItemsToProducer_OneSentOrder()
{
//Arrange
Order order = new Order();
Guest guest = new Guest(1, order);
Producer producer = new Producer("Thomas", "Guldborg", "Beverage producer");
DataGridView dataGridView = new DataGridView { BindingContext = new BindingContext() };
order.MenuItemId = 1;
order.Quantity = 1;
//Act
guest.AddItem();
dataGridView.DataSource = guest.SendOrderOverview();
guest.SendOrder(dataGridView);
dataGridView.DataSource = producer.OrderOverview();
var guestTableOrder = producer.OrderOverview()
.Where(orders => orders.gtid == guest.GuestTableId)
.Select(producerOrder => producerOrder.gtid)
.Single();
//Assert
Assert.That(guestTableOrder, Is.EqualTo(guest.GuestTableId));
}
如果你在class中继续绑定sql,你的测试问题不大。
当程序逻辑很简单的时候可以使用这个方法,但是我建议你研究一下The Repository Pattern,因为逻辑越来越复杂
是的,一般来说,这就是编写单元test/integration测试的方法。您遵守一些重要准则:
- 不同的 Act-Arrange-Assert 步骤
- 测试名称描述了这些步骤(也许它最后应该有类似"ShouldSendOneOrder"的东西,"Should"通常用于描述Assert)。
- 每个测试一个断言。
我假设您还遵守其他准则:
- 测试是独立的:它们不会改变持久状态,因此不会影响其他测试。
- 测试真实用例:不安排违背业务逻辑的星座,不做不可能的事。或者:模仿真实的应用程序。
不过,我也看到了令人侧目的事情。
不清楚你测试的是哪个动作。我认为有些"acts"属于排列步骤
producer.OrderOverview()
这样的方法让我怀疑领域对象执行数据库交互。如果是这样,这将违反 持久性无知 。我认为应该有一个服务提供这种方法(但见下文)。
不清楚为什么 dataGridView.DataSource = producer.OrderOverview();
是测试所必需的。如果是,这只会加剧最严重的一点:
业务逻辑和UI纠缠不清!!
- 像
guest.SendOrderOverview()
和 producer.OrderOverview()
这样的方法 很臭 :为什么领域对象应该知道如何 present它的内容?这是演示者 (MVP) 或控制器 (MVC) 或视图模型 (MVVM) 应该负责的事情。
- 像
guest.SendOrder(dataGridView)
这样的方法是恶。它将领域层与 UI 框架联系起来。这种固定的依赖关系已经够邪恶了,但是当然你还需要这个方法中网格视图的值。因此,业务逻辑需要对某些 UI 组件有深入的了解。这违反了告诉-不要问原则。 guest.SendOrder
应该有简单的参数来告诉它如何完成它的任务,域不应该 any 引用 any UI框架。
你真的应该解决后一点。在不与 DGV 进行任何交互的情况下,将运行此测试作为你的目标。
我们是两个正在写学士论文的学生,我们开发了一个 Windows 应用程序,它应该能够在各种沟通过程中帮助餐厅。从根本上说,它应该能够从客人发送给它的那一刻起就显示有关订单的信息。
我们在开发过程中省略了测试,但现在决定编写单元测试。尽管如此,我们发现我们现在可以写入系统的最合适的测试是集成测试,因为我们 类 中的所有方法都通过 LINQ to SQL 绑定到 SQL 存储过程.我们知道使用存根来伪造对数据库的依赖性,但是当我们的数据库已经与所有功能一起实现时,我们认为将几种方法作为集成测试一起测试会给我们带来更多价值。
如以下代码所示,我们已尝试遵循单元测试的指南,但这是编写集成测试的正确方法吗?
[Test]
public void SendTotalOrder_SendAllItemsToProducer_OneSentOrder()
{
//Arrange
Order order = new Order();
Guest guest = new Guest(1, order);
Producer producer = new Producer("Thomas", "Guldborg", "Beverage producer");
DataGridView dataGridView = new DataGridView { BindingContext = new BindingContext() };
order.MenuItemId = 1;
order.Quantity = 1;
//Act
guest.AddItem();
dataGridView.DataSource = guest.SendOrderOverview();
guest.SendOrder(dataGridView);
dataGridView.DataSource = producer.OrderOverview();
var guestTableOrder = producer.OrderOverview()
.Where(orders => orders.gtid == guest.GuestTableId)
.Select(producerOrder => producerOrder.gtid)
.Single();
//Assert
Assert.That(guestTableOrder, Is.EqualTo(guest.GuestTableId));
}
如果你在class中继续绑定sql,你的测试问题不大。
当程序逻辑很简单的时候可以使用这个方法,但是我建议你研究一下The Repository Pattern,因为逻辑越来越复杂
是的,一般来说,这就是编写单元test/integration测试的方法。您遵守一些重要准则:
- 不同的 Act-Arrange-Assert 步骤
- 测试名称描述了这些步骤(也许它最后应该有类似"ShouldSendOneOrder"的东西,"Should"通常用于描述Assert)。
- 每个测试一个断言。
我假设您还遵守其他准则:
- 测试是独立的:它们不会改变持久状态,因此不会影响其他测试。
- 测试真实用例:不安排违背业务逻辑的星座,不做不可能的事。或者:模仿真实的应用程序。
不过,我也看到了令人侧目的事情。
不清楚你测试的是哪个动作。我认为有些"acts"属于排列步骤
producer.OrderOverview()
这样的方法让我怀疑领域对象执行数据库交互。如果是这样,这将违反 持久性无知 。我认为应该有一个服务提供这种方法(但见下文)。不清楚为什么
dataGridView.DataSource = producer.OrderOverview();
是测试所必需的。如果是,这只会加剧最严重的一点:业务逻辑和UI纠缠不清!!
- 像
guest.SendOrderOverview()
和producer.OrderOverview()
这样的方法 很臭 :为什么领域对象应该知道如何 present它的内容?这是演示者 (MVP) 或控制器 (MVC) 或视图模型 (MVVM) 应该负责的事情。 - 像
guest.SendOrder(dataGridView)
这样的方法是恶。它将领域层与 UI 框架联系起来。这种固定的依赖关系已经够邪恶了,但是当然你还需要这个方法中网格视图的值。因此,业务逻辑需要对某些 UI 组件有深入的了解。这违反了告诉-不要问原则。guest.SendOrder
应该有简单的参数来告诉它如何完成它的任务,域不应该 any 引用 any UI框架。
- 像
你真的应该解决后一点。在不与 DGV 进行任何交互的情况下,将运行此测试作为你的目标。