模拟数据库事务? [英] Mocking Database transactions?

查看:70
本文介绍了模拟数据库事务?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一对具有父/子关系的表-事件和identityDetails.我有一个视图模型,其中包含来自这两个表的信息.我有一个业务层方法,该方法传递了需要更新两个表的viewmodel实例.

因此,在该方法中,我使用的是EF6的新交易机制:

  using(var transaction = this.db.Database.BeginTransaction()){尝试{//各种数据库资料this.db.SaveChanges();//更多数据库资料this.db.SaveChanges();//还有更多数据库资料this.db.SaveChanges();transaction.Commit();}抓住(前例外){transaction.Rollback();this.logger.logException(例如,事务中捕获了异常,正在回滚");扔;}} 

所以,我的问题.我该如何测试?

我在Moq上使用Microsoft的单元测试框架,并且在模拟DBContexts和DbSet 时没有遇到麻烦,但是我似乎无法弄清楚如何解决事务./p>

如果我不尝试模拟事务,则会收到InvalidOperationException:

在应用程序中找不到名为xxx的连接字符串配置文件."

这很合理-没有应用程序配置文件,也没有数据库.

但是,如果我尝试模拟BeginTransaction(),则会收到初始化错误:NotSupportedException:

在非虚拟成员上的无效设置:m =>m.Database.BeginTransaction".

那让我开始研究杂草,研究.NET方法的反编译,试图确定某些可能源自可用接口的类,或以某种方式可以注入模拟对象的东西.

我不是要对MS的事务代码进行单元测试-我只想确保对每个表中的相应记录进行了适当的更改.但就目前看来,这似乎是不可测试的,并且使用事务的任何方法都是不可测试的.那只是一个痛苦.

我在Google周围搜索,没有发现任何用处.有人遇到过这个问题吗?任何人都有关于如何进行的想法吗?

解决方案

测试这种东西总是很复杂,但是首先您应该问自己是否要对业务逻辑进行单元测试或是否要进行集成测试您的应用程序.

如果您想对逻辑进行单元测试,则基本上甚至不应该尝试模拟实体框架,因为您不想测试EF,而只是想测试代码,对吗?为此,请模拟任何数据访问对象,并仅对您的业务逻辑进行单元测试.

但是,如果您想测试数据访问层是否正常工作,例如如果您的代码可以处理您已实现的所有CRUD操作,则应针对真实数据库进行集成测试.在这种情况下,请勿尝试模拟任何数据访问对象(EF),只需针对测试数据库或sql-express localDB运行测试.

I have a pair of tables with a parent/child relationship - incident and incidentDetails. I have a viewmodel that contains information from both of these tables. And I have a business layer method that is passed an instance of the viewmodel that needs to update both tables.

So, in the method, I'm using EF6's new transaction mechanism:

using (var transaction = this.db.Database.BeginTransaction())
{
    try
    {
        // various database stuff
        this.db.SaveChanges();
        // more database stuff
        this.db.SaveChanges();
        // yet more database stuff
        this.db.SaveChanges();

        transaction.Commit();
    }
    catch (Exception ex)
    {
        transaction.Rollback();
        this.logger.logException(ex, "Exception caught in transaction, rolling back");
        throw;
    }
}

And so, my problem. How do I test this?

I'm using Microsoft's unit testing framework, with Moq, and I have had no trouble with mocking up DBContexts, and DbSet<>s, but I can't seem to figure out how to get around the transaction stuff.

If I don't attempt to mock the transaction, I get an InvalidOperationException:

"No connecting string named xxx could be found in the application config file."

Which makes perfect sense - there isn't an application config file, and there isn't any database.

But if I try to mock BeginTransaction(), I get initialization errors: NotSupportedException:

"Invalid setup on a non-virtual member: m => m.Database.BeginTransaction".

And that got me chasing into the weeds, looking at decompiles of the .NET methods, trying to identify some class that might derive from a usable interface, or something, where I could somehow inject a mocking object.

I'm not trying to unit-test MS's transactional code - I just want to make sure that the appropriate changes are made to the appropriate records in each of the tables. But as it sits, it looks like this is non-testable, and that any method that uses transactions is non-testable. And that's just a pain.

I've Googled around, and not found anything of use. Has anyone run into this issue? Anyone have ideas on how to proceed?

解决方案

Testing this kind of stuff is always complicated, but first of all you should ask yourself if you want to unit test your business logic or if you want to integration test your application.

If you want to unit test your logic, you basically shouldn't even try to mock entity framework, because you do not want to test EF, you just want to test your code, right? To do so, mock any data access object and only unit test your business logic.

But if you want to test if your data access layer works, e.g. if your code can handle all the CRUD operations you have implemented, you should do integration tests against a real database. Do not try to mock any data access objects (EF) in this case, simply run you tests against a test database or a sql-express localDB for example.

这篇关于模拟数据库事务?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆