猿问

在 C# 中使用 Moq 模拟服务

我有一个以这种方式设置的服务。


public Interface IDataService : IDisposable

{

    IQueryable<T> Set<T>() where T : class;


    IDbSet<T> WritableSet<T>() where T : class;

}

IDataService 由 DataService 继承。


public abstract class DataService : IDataService

{

    public IDataContext DataContext { get; private set; }


    public IQueryable<T> Set<T>() where T : class

    {

        return DataContext.Set<T>().AsNoTracking();

    }


    public IDbSet<T> WritableSet<T>() where T : class

    {

        return DataContext.Set<T>();

    }


    public AddResult<T> Add<T>(T obj) where T : class, IPersistentEntity

    {

        if (obj == null)

            return new AddResult<T>() { IsValid = false };

        else

        {

            if (obj.Id == Guid.Empty)

                WritableSet<T>().Add(obj);


            bool success = DataContext.SaveChanges() > 0;


            return new AddResult<T>() { Entity = obj, IsValid = success };

        }

    }

}

并且 DataService 是由 EntityService 继承的。


public class EntityService : DataService

{

    public EntityService(IDataContext DataContext) : base(DataContext)

    {

    }


    public void EntityStarted(Guid Id)

    {

        var a = GetWriteableById<Entity>(Id);

        a.Status = 1;

        DataContext.SaveChanges();

    }

}

此 EntityService 用于我的一个组件中。EntityService 的对象被创建并传递给组件的构造函数。


我正在使用 Moq 对组件执行一些测试,为此,计划是模拟 EntityService,以便 EntityService 使用带有虚拟数据的假数据库容器进行类似数据库的操作。但是,我没有最好的主意用最少的新代码来模拟这个。


我拥有的最不吸引人的想法是使用接口创建一个假的 EntityService 类,并拥有适合测试的自己的实现。


帮助表示赞赏!:)


跃然一笑
浏览 290回答 2
2回答

catspeake

根据@JLe 和@Chetan 对这个问题的评论,我不得不模拟 DbContext。我按照这篇文章来模拟 DbContext。使用 Moq 模拟 DbContext这是代码的样子。&nbsp; &nbsp; private void Setup()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; List<Entity> entityData = new List<Entity>();&nbsp; &nbsp; &nbsp; &nbsp; entityData.Add(new Entity&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Id = Guid.NewGuid()&nbsp; &nbsp; &nbsp; &nbsp; });&nbsp; &nbsp; &nbsp; &nbsp; DbSet<Entity> MockEntitySet = GetSet(entityData);&nbsp; &nbsp; &nbsp; &nbsp; MockContext = new Mock<IDbContext>();&nbsp; &nbsp; &nbsp; &nbsp; MockContext.Setup(m => m.Set<Entity>()).Returns(MockEntitySet);&nbsp; &nbsp; }&nbsp; &nbsp; public static DbSet<T> GetSet<T>(List<T> sourceList) where T : class&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; return GetSet(sourceList.ToArray());&nbsp; &nbsp; }&nbsp; &nbsp; public static DbSet<T> GetSet<T>(T[] sourceList) where T : class&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; var name = typeof(T).Name;&nbsp; &nbsp; &nbsp; &nbsp; var queryable = sourceList.AsQueryable();&nbsp; &nbsp; &nbsp; &nbsp; Mock<DbSet<T>> dbSet = new Mock<DbSet<T>>();&nbsp; &nbsp; &nbsp; &nbsp; dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);&nbsp; &nbsp; &nbsp; &nbsp; dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);&nbsp; &nbsp; &nbsp; &nbsp; dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);&nbsp; &nbsp; &nbsp; &nbsp; dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());&nbsp; &nbsp; &nbsp; &nbsp; dbSet.Setup(m => m.AsNoTracking()).Returns(dbSet.Object);&nbsp; &nbsp; &nbsp; &nbsp; return dbSet.Object;&nbsp; &nbsp; }&nbsp; &nbsp; [TestMethod]&nbsp; &nbsp; public void Test()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; EntityService service = new EntityService(MockContext.Object);&nbsp; &nbsp; &nbsp; &nbsp; ComponentToTest compObj = new ComponentToTest(service);&nbsp; &nbsp; &nbsp; &nbsp; compObj.MethodToTest(...);&nbsp; &nbsp; &nbsp; &nbsp; // Assertions&nbsp; &nbsp; }感谢你们!感谢您的帮助和建议。

GCT1015

要模拟你需要一个接口,如果没有,你需要将要模拟的方法标记为虚拟。在幕后,模拟框架将为您创建一个新的实现,其行为与您配置模拟一样。希望能帮助到你。
随时随地看视频慕课网APP
我要回答