我有以下方法:如何为更改数据的方法编写单元测试?
Void UpdateUser(User user){}
我需要检查这个方法是否能正常工作。
我已经使用一个单独的数据库来检查这在单元测试。但是很多有经验的人说如果我用这种方法不是单元测试的话;这就是集成测试。
但我不知道如何模拟单元测试。
在UpdateUser
方法中编写的代码将尝试使用实体框架更新数据。
如果我嘲笑(其实我也不怎么这样做),这将如何与实体框架一起工作?
我有以下方法:如何为更改数据的方法编写单元测试?
Void UpdateUser(User user){}
我需要检查这个方法是否能正常工作。
我已经使用一个单独的数据库来检查这在单元测试。但是很多有经验的人说如果我用这种方法不是单元测试的话;这就是集成测试。
但我不知道如何模拟单元测试。
在UpdateUser
方法中编写的代码将尝试使用实体框架更新数据。
如果我嘲笑(其实我也不怎么这样做),这将如何与实体框架一起工作?
模拟意味着你开发你的软件组件(类)的方式是任何具有行为的类都被使用/消费/作为接口(或抽象类)调用。你编程抽象。运行时您使用某些东西(服务定位器,DI容器,工厂等)来检索/创建这些实例。
最常用的方法是用施工注塑。 Here是一个很好的解释,为什么会使用DI,以及如何做到这一点的例子。
在你的情况下,你使用实体框架的组件(你的仓库的实例)必须实现一个仓库界面,任何使用仓库的类都应该使用它作为界面。
这样,你可以模拟你的unittests中的存储库。这意味着你创建了一个unit-test-repository类(与任何数据库或EF无关),并且在你创建你想要单元测试的类的实例时使用它。
使用事务,并在测试
是的,这就是我在做什么?但无论如何,人们说嘲笑。我也觉得这是编程的好方法 –
-1这根本不是*单元测试*的方式。 –
@KeithPayne,如何做单元测试?如何模拟? –
可以使用事务和回滚或创建测试用户尝试的更新结束时回滚事务。断言,然后在finally块中删除测试用户。
你可以使用像moq,rhino等模拟框架。moq很容易,你可以找到许多用DI像统一框架来演示moq的例子。
-1回滚数据库正在测试,但它不是*单元测试*。 –
@KeithPayne,请发表你对我所问的答案。我必须做单元测试,而不是集成测试。请发表您的宝贵答案 –
@DavidArno由于您无法在单元测试的上下文中锁定数据库以防止另一个进程修改底层数据,因此无法确定。如果其他类似的与数据库相关的测试同时运行,并且所有这些测试都没有通过所有其他可能的测试知识来防止意外数据编码,则它将失败。 –
如果你的类是这样
public class UserRepository()
{
Sqlcontext _context;
void UpdateUser(User user)
{
_context.Users.Add(user);
}
}
那么这是不是单元测试。
虽然这不是一个单元测试,如果你坚持连接数据库并对其进行测试,则可以将功能改成
User UpdateUser(User user)
{
_context.Users.Add(user);
return user;
}
和测试,如果
user.Id > 0
在这里,你是基本上只是测试实体框架。
“我用一个单独的数据库单元测试,以检查它。但是许多 有经验的人说,如果我用这个方法不会是单元测试 ;。这是集成测试”
这些人是错误的,尽管他们假设的经验。出于某种原因,单元测试都是关于单独测试代码部分的错误概念近年来越来越流行。实际上,单元测试都是关于编写作为一个单元的测试,换句话说,它们是孤立存在的,一个单元测试的结果不会影响另一个测试。
如果您的UpdateUser
方法直接访问EF,那么只要您确保数据库保证在每次测试结束时回滚到其开始状态,那么您将进行单元测试。但是,为每个测试设置数据库并确保其可靠地回滚可能需要很多工作。这就是为什么经常使用嘲笑。其他答案已经涵盖了mcoking EF,所以我不会重复一遍。
为了极大地简化您的测试,您可以在UpdateUser
和EF之间插入一层外推层。换句话说,UpdateUser
类提供了一个接口实例,该实例是其进入EF的网关。它不直接与EF交谈。然后模拟EF,你只需提供一个模拟的接口实现。然后,这就将测试对象EF的需求推向了更基本的层次,并带有更多基本的类似于CRUD的行为。
由于您比其他人所看到的经验更加尊重,所以问题不在于隔离,而在于数据库的性质。如果OP在每个线程上使用单独的数据库实例,那么通过数据库进行测试可以是单元测试。即使是从单独组件反弹的测试,也可以进行单元测试,只要测试是快速,自动化,隔离和确定性的。测试数据库时,确定性是杀手级的。没有任何方法可以消除来自其他进程/线程的意外数据的可能性。 –
@KeithPayne,该死的,我发现自己不得不同意你的看法。 :) 当考虑到并行运行测试时,数据库测试确实不能进行单元测试。真正的单元测试必须支持并行运行。 –
使用实体框架模拟数据库有数百个博客和数千个问题。你尝试了什么,你发现了什么,没有发现什么? – CodeCaster
您想要了解的基础问题是如何实现依赖注入。我建议在那里开始你的研究。 [为什么使用依赖注入?](http://stackoverflow.com/q/14301389/580951) – Romoku
请发布您的自定义数据上下文类 - 一个包含'DbSet'属性,以便我可以发布答案与您的设置相符。 –