单元测试数据存储

时间:2009-03-29 14:45:58

标签: unit-testing

假设我有一个方法'storeData(key,data)'和'getData(key)'的接口。我该如何测试具体的实现?我应该检查数据是否在存储介质中正确设置(例如sql数据库),还是应该检查它是否通过使用getData来提供正确的数据?

如果我在数据库中查找数据,感觉我也在测试方法的内部,但只检查它是否给出了相同的数据,感觉不完整。

5 个答案:

答案 0 :(得分:2)

您似乎陷入了单元测试的炒作,您将要做的实际上是集成测试。从同一个密钥设置和获取相同的值是对存储引擎的模拟实现进行的单元测试,但实际测试真实存储,比如数据库,就像你应该的那样,不再是单元测试,但它是测试的基本部分,听起来像是对我的集成测试。不要将单元测试用作锤子,为正确的工作选择合适的工具。将您的测试划分为更多层。

答案 1 :(得分:2)

您希望在单元测试中执行的操作是确保该方法完成它应该执行的工作。如果该方法使用依赖项来完成它的工作,那么您将模拟这些依赖项,并确保您的方法使用适当的参数调用它所依赖的对象上的方法。这样您就可以单独测试代码。

这样做的好处之一是它可以更好地推动代码设计。例如,为了使用模拟,您自然会倾向于使用依赖注入来解耦更多的代码。这使您能够轻松地将模拟对象替换为您的类所依赖的实际对象。您最终还是实现了接口,这些接口更自然地被嘲笑。这两件事都是很好的设计模式,会改进你的代码。

例如,为了测试您的特定示例,您可能让您的类依赖于工厂来创建与数据库的连接,并使用构建器来构造通过连接执行的参数化SQL命令。您将这些对象的这些模拟版本传递给您的类,并确保调用正确的方法来设置连接和命令,构建正确的命令,执行它并拆除连接。或者,您可能注入一个已打开的连接,只需构建命令并调用它即可。关键是你的类是针对一个接口或一组接口构建的,你使用mocking来提供实现这些接口的对象,并且可以记录调用并为你希望从接口使用的方法提供正确的返回值。 / p>

答案 2 :(得分:1)

在这种情况下,我通常会创建在单元测试之前/之后触发的SetUp和TearDown方法。这些方法将在db中设置我需要的任何测试数据,并在完成后删除任何测试数据。伪代码示例:

Const KEY1 = "somekey"
Const VALUE1= "somevalue"


Const KEY2 = "somekey2"
Const VALUE2= "somevalue2"



Sub SetUpUnitTests()
{
   Insert Into SQLTable(KEY1,VALUE1)
}


//this test is not dependent on the setData Method
Sub GetDataTest()
{
   Assert.IsEqual(getData(KEY1),VALUE1)
}

//this test is not dependent on getData Method
Sub SetDataTest()
{
   storeData(newKey,NewData)
   Assert.IsNotNull(Direct Call to SQL [Select data from table where key=KEY2]) 

}

Sub TearDownUnitTests()
{
   Delete From table Where key in (KEY1, KEY2)
} 

答案 3 :(得分:0)

我认为这取决于以后数据会发生什么 - 如果您只是使用storeDatagetData访问数据,为什么不一致地测试这些方法?我想有可能会出现一个错误,而且要弄清楚它是在storeData还是getData还是稍微有些困难,但我认为这是一个可接受的风险

  1. 使您的测试更容易实施,
  2. 隐藏内部,如你所说
  3. 如果使用其他机制从数据库中读取数据或将数据插入数据库,那么我会按照您的建议使用SQL检查数据库。

    @brendan提出了一个很好的观点 - 无论你决定使用哪种方法,你都会在数据库中插入数据。在测试之前和之后清除数据是个好主意,以确保您可以获得一致的结果。

答案 4 :(得分:0)

在音乐会上进行测试是一种常见的技术(至少,根据我的经验),我不会回避它。我已经使用相同的模式进行序列化/反序列化以及解析和打印。

如果您不想访问数据库,可以使用数据库模拟。有些人在使用模拟时与你有同样的感受 - 这部分是特定于实现的。就像在所有方面一样,这是一个权衡:考虑模拟的好处(更快,而不是数据库依赖)与其缺点(不会检测实际的数据库问题,更慢)。