2011-11-18 62 views
1

我有这样的方法如下:如何测试具有数据库查询以更新数据的方法?

public void ImportDataCommand() 
{ 
    // some data validation logic here 

    if (some_criteria_is_true) 
    { 
     // Call to a method which uses sql queries to update some records 
     UpdateRecords(); 
    } 
    else 
    { 
     // Call to a method which uses sql queries to delete some records 
     DeleteRecords(); 
    } 
} 
  • 我怎么能单元测试方法UpdateRecords()DeleteRecords()? (如果可能的话)
  • 我目前的模式, 的气味?
  • 有没有更好的方法来处理,当你有一些数据 更新逻辑,这取决于一些数据验证逻辑和一些 条件逻辑?

在这方面的任何帮助,非常感谢。请让我知道,如果你需要更多的信息,或者如果有什么不明确的。

更新:

我没有兴趣在这里嘲讽的数据源。我想确保我的sql查询是否正确,并且正在做正确的更新。对不起,如果你想,我想测试我的验证逻辑,而不是我的数据更新逻辑(sql)。

我确实有嘲笑框架的经验,我成功地使用它们为我的正常应用程序逻辑编写单元测试。

+0

你的方法不会返回任何东西 - 通常,单元测试会给你一堆参数,并测试返回的值是否符合期望值。 –

+0

@尼维尔:对。比方说,我想测试一个应用程序命令,它将数据存储/更新到数据库中。有没有办法做到这一点? - 我已经使用NUnit为我的正常应用程序逻辑成功编写了单元测试。 –

+0

执行此操作的常用方法是使用模拟框架,因此您可以将测试与其下的特定数据库分离。 –

回答

3

您的问题始于短语'以及'

不要在同一个类中进行验证和数据访问 - 将数据访问委派给另一个类并注入它 - 这样,您可以在测试验证时嘲笑数据源。

class Bar { 
private DataAccessService service 

public void Foo() 
{ 
    // some data validation logic here 

    if (some_criteria_is_true) 
    { 
     // Call to a method which uses sql queries to update some records 
     service.updateBarRecords(); 
    } 
    else 
    { 
     // Call to a method which uses sql queries to delete some records 
     service.deleteBarRecords(); 
    } 
} 

} 

然后,您可以使用模拟框架来测试是否调用了正确的服务方法。

+0

对不起,我感到困惑。我想测试我的数据更新逻辑而不是验证逻辑。请参阅我对该问题所做的更新。 –

+0

如果Foo()不是你想测试的方法,那么你可能应该问一个关于如何测试UpdateBarRecords()的问题...... – blank

+0

你是对的。我现在更新了我的问题以反映这一点。谢谢。 –

0

这取决于您的应用程序的整个架构和公司的IT/DB基础架构,以及数据库管理员可以在中型企业或大公司中强制执行的数据策略。

过去人们曾经为SQLite实例进行单元测试,或者您可以使用相同的技术(例如SQL Server),但有单元测试连接到开发或QA数据库服务器,当然不是生产。

我过去做过的一件事是在命令执行周围进行事务处理,最后在单元测试中回滚事务,因此DEV/QA数据库中没有任何内容持久化,但命令执行的测试无论如何都是执行的。

+0

您通常会嘲笑数据库本身来进行单元测试,而不是在生产数据库上进行单元测试,因为您必须注意回滚和填充内容。我从以前的项目中看到的是,他们使用NUNIT构建的预处理器指令,然后将SQL执行重定向到一个不同的(注入)数据库,在这里你不需要关心回滚或以前的事情。在每件事情完成后删除就是kool。 :) – Zenwalker

0

当你做单元测试时,你特别只关注那个单元,例如这里的一个方法。所以当你编写一个测试用例时,你可以模拟通常通过依赖注入调用的其他方法(如果它是API调用或某种东西)。其他方面,你只是猜测和写出测试用例。因此,在您的代码案例中,假设您分别为Foo(),UpdateBarRecords()和DeleteBarRecords()编写测试用例。

忽略所有的方法调用(对它进行单元测试)并专注于您在该方法中编写的核心逻辑代码,这些代码将专注于单元测试。

0

恕我直言,你应该解决您的代码这个问题:

  1. 富不是单位testeable,因为它不返回任何东西
  2. 你连接到你的应用程序逻辑的数据访问,这使得不同的层太捆绑在一起,实际上单元测试它们
  3. 也许一种方法,您根据某种条件调用更新和删除是一种气味......应该不是更好有两种不同的行为?

既然Foo的命名不是自我解释,那么没有其他的东西了,但是如果你能详细描述方法的上下文,我们可以添加更多的评论。

+2

不返回东西不会使它无法测试 – blank

+0

@Bedwyr,除非我遗漏了我确认的东西:您可以测试一次执行该方法的可见效果,但是您不能单元测试*方法*本身。 – mamoo

+0

您可以测试该方法是否具有正确的行为 - 它必须执行某些操作 - 这就是您可以测试的方法,可以通过声明状态已在类中的其他位置进行更改,或者方法调用依赖性上的预期方法。 – blank