起订量,让过去的实体框架的BeginTransaction [英] Moq, getting past entity framework BeginTransaction

查看:288
本文介绍了起订量,让过去的实体框架的BeginTransaction的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让嘲弄在单元测试的意识和单元测试过程集成到我的项目。所以,我一直走直通几个教程和重构我的代码,以支持嘲讽,反正我是无法通过测试,因为DB方法,我想测试使用事务,但创建一个交易的时候,我得到

I am trying to make sense of mocking in unit testing and to integrate the unit testing process to my project. So I have been walking thru several tutorials and refactoring my code to support mocking, anyway, I am unable to pass the tests, because the DB method I am trying to test is using a transaction, but when creating a transaction, I get

基础提供开放式失败。

如果没有交易一切正常就好了。

Without transaction everything works just fine.

我目前拥有的代码是:

[TestMethod]
public void Test1()
{
    var mockSet = GetDbMock();
    var mockContext = new Mock<DataContext>();
    mockContext.Setup(m => m.Repository).Returns(mockSet.Object);

    var service = new MyService(mockContext.Object);
    service.SaveRepository(GetRepositoryData().First());
    mockSet.Verify(m => m.Remove(It.IsAny<Repository>()), Times.Once());
    mockSet.Verify(m => m.Add(It.IsAny<Repository>()), Times.Once());
    mockContext.Verify(m => m.SaveChanges(), Times.Once());
}

// gets the DbSet mock with one existing item
private Mock<DbSet<Repository>> GetDbMock()
{
    var data = GetRepositoryData();
    var mockSet = new Mock<DbSet<Repository>>();

    mockSet.As<IQueryable<Repository>>().Setup(m => m.Provider).Returns(data.Provider);
    // skipped for brevity
    return mockSet;
}

代码测试:

private readonly DataContext _context;
public MyService(DataContext ctx)
{
    _context = ctx;
}

public void SaveRepositories(Repository repo)
{
    using (_context)
    {
        // Here the transaction creation fails
        using (var transaction = _context.Database.BeginTransaction())
        {
            DeleteExistingEntries(repo.Id);
            AddRepositories(repo);
            _context.SaveChanges();
            transaction.Commit();
        }
    }
}



我试图嘲弄交易部分,以及:

I was trying to mock the transaction part as well:

var mockTransaction = new Mock<DbContextTransaction>();
mockContext.Setup(x => x.Database.BeginTransaction()).Returns(mockTransaction.Object);



但这不是工作,与失败的:

but this is not working, failing with:

非虚拟(VB中重写)成员无效设置:康恩=>
conn.Database.BeginTransaction()

Invalid setup on a non-virtual (overridable in VB) member: conn => conn.Database.BeginTransaction()

任何想法如何解决这个问题?

Any ideas how to solve this?

推荐答案

作为第二个错误消息称,最小起订量无法模拟非虚方法或属性,所以这种做法是行不通的。我建议使用适配器模式来解决这个问题。我们的想法是创建一个适配器的与相互作用(即实现了一些接口的包装类)在的DataContext ,并通过执行所有数据库活动接口。然后,你可以嘲笑接口而不是

As the second error message says, Moq can't mock non-virtual methods or properties, so this approach won't work. I suggest using the Adapter pattern to work around this. The idea is to create an adapter (a wrapper class that implements some interface) that interacts with the DataContext, and to perform all database activity through that interface. Then, you can mock the interface instead.

public interface IDataContext {
    DbSet<Repository> Repository { get; }
    DbContextTransaction BeginTransaction();
}

public class DataContextAdapter {
    private readonly DataContext _dataContext;

    public DataContextAdapter(DataContext dataContext) {
        _dataContext = dataContext;
    }

    public DbSet<Repository> Repository { get { return _dataContext.Repository; } }

    public DbContextTransaction BeginTransaction() {
        return _dataContext.Database.BeginTransaction();
    }
}



你的所有代码,以前使用的<$ C的$ C>的DataContext 直接现在应该使用 IDataContext ,这应该是一个 DataContextAdapter 时在程序运行,但在测试中,你可以很容易地嘲笑 IDataContext 。这应该使嘲讽方式更简单一点,因为你可以设计 IDataContext DataContextAdapter 来隐藏一些实际的复杂性的DataContext

All of your code that previously used the DataContext directly should now use an IDataContext, which should be a DataContextAdapter when the program is running, but in a test, you can easily mock IDataContext. This should make the mocking way simpler too because you can design IDataContext and DataContextAdapter to hide some of the complexities of the actual DataContext.

这篇关于起订量,让过去的实体框架的BeginTransaction的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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