似乎无法添加EF CodeFirst 4.1.可以帮助任何人吗? [英] Cannot seem to moq EF CodeFirst 4.1.Help anyone?

查看:77
本文介绍了似乎无法添加EF CodeFirst 4.1.可以帮助任何人吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经获得了评估codeFirst的任务,并有可能用于我们未来的所有项目. 评估基于将CodeFirst与现有数据库一起使用.

I have been given the task to evaluate codeFirst and possible to use for all our future projects. The evaluation is based on using codeFirst with an existing database.

想知道是否可以使用codeFirst 4.1来模拟存储库.(无伪造品)

Wondering if it's possible to mock the repository using codeFirst 4.1.(no fakes)

这个想法是将一个存储库注入到服务中,然后对该存储库进行定量.

The idea is to inject a repository into a service and moq the repository.

我一直在网上寻找,但是我只发现了一个使用假货的例子.我不想使用我想使用最小起订量的假货.

I have been looking on the net but I have only found an example using fakes.I dont want to use fakes I want to use moq.

我认为我的问题出在DAL的体系结构中.(我想使用unitOfWork等.我需要显示一个有效的最小起订量示例)

I think my problem is in the architecture of the DAL.(I would like to use unitOfWork etc.. by I need to show a working moq example)

以下是我的尝试(惨遭失败),原因是我对Code first 4.1的知识不足. 我还上传了一个解决方案,以防万一有人心情很好并且想要更改它.

Below is my attempt(Failed miserably) due to lack of knowledge on Code first 4.1. I have also uploaded a solution just in case somebody is in good mood and would like to change it.

http://cid-9db5ae91a2948485.office. live.com/browse.aspx/Public%20Folder?uc=1

我乐于接受建议和对Dal进行全面修改.理想情况下使用Unity等. 最重要的是,我需要能够模拟它.如果无法使用最小起订量,我们将使用EF 4.1对该项目进行分箱

I am open to suggestions and total modification to my Dal.Ideally using Unity etc.. but I will worry about later. Most importantly I need to be able to mock it. Without ability to use MOQ we will bin the project using EF 4.1

尝试失败

//CodeFirst.Tests Project
[TestClass]
public class StudentTests
{
    [TestMethod]
    public void Should_be_able_to_verify_that_get_all_has_been_called()
    {
        //todo redo test once i can make a simple one work
        //Arrange
        var repository = new Mock<IStudentRepository>();
        var expectedStudents = new List<Student>();
        repository.Setup(x => x.GetAll()).Returns(expectedStudents);

        //act
        var studentService = new StudentService(repository.Object);
        studentService.GetAll();

        //assert
        repository.Verify(x => x.GetAll(), Times.AtLeastOnce());
    }

}

//CodeFirst.Common Project
public class Student
{
    public int StudentId { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
}
public interface IStudentService
{
    IEnumerable<Student> GetAll();
}

//CodeFirst.Service Project
public class StudentService:IStudentService
{
    private IStudentRepository _studentRepository;

    public StudentService()
    {
    }

    public StudentService(IStudentRepository studentRepository)
    {
        _studentRepository = studentRepository;
    }


    public IEnumerable<Student> GetAll()
    {
        //TODO when mocking using moq this will actually call the db as we need a separate class.
        using (var ctx = new SchoolContext("SchoolDB"))
        {
            _studentRepository = new StudentRepository(ctx);
            var students = _studentRepository.GetAll().ToList();
            return students;
        } 
    }
}

//CodeFirst.Dal Project
public interface IRepository<T> where T : class
{
    T GetOne(Expression<Func<T, bool>> predicate);
    IEnumerable<T> GetAll();
    IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
    void Add(T entity);
    void Delete(T entity);
    T Single(Func<T, bool> predicate);
    T First(Func<T, bool> predicate);
}
public class RepositoryBase<T> : IRepository<T> where T : class
{
    private readonly IDbSet<T> _dbSet;

    public RepositoryBase(DbContext dbContext)
    {
        _dbSet = dbContext.Set<T>();
        if (_dbSet == null) throw new InvalidOperationException("Cannot create dbSet ");
    }

    protected virtual IDbSet<T> Query
    {
        get { return _dbSet; }
    }

    public T GetOne(Expression<Func<T, bool>> predicate)
    {
        return Query.Where(predicate).FirstOrDefault();
    }

    public IEnumerable<T> GetAll()
    {
        return Query.ToArray();
    }

    public IEnumerable<T> Find(Expression<Func<T, bool>> predicate)
    {
        return Query.Where(predicate).ToArray();
    }

    public void Add(T entity)
    {
        _dbSet.Add(entity);
    }

    public void Delete(T entity)
    {
        _dbSet.Remove(entity);
    }


    public T Single(Func<T, bool> predicate)
    {
        return Query.Where(predicate).SingleOrDefault();
    }

    public T First(Func<T, bool> predicate)
    {
        return Query.Where(predicate).FirstOrDefault();
    }

}
 public class SchoolContext:DbContext
{
    public SchoolContext(string connectionString):base(connectionString)
    {
        Database.SetInitializer<SchoolContext>(null);
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        //Not sure why I have to do this.Without this when using integration testing
        //as opposed to UnitTests it does not work.
        modelBuilder.Entity<Student>().ToTable("Student");       }


    public DbSet<Student> Students { get; set; }
}
public interface IStudentRepository:IRepository<Student>
{

}
public class StudentRepository : RepositoryBase<Student>, IStudentRepository
{
    public StudentRepository(DbContext dbContext)
        : base(dbContext)
    {
    }

    public IEnumerable<Student> GetStudents()
    {
        return GetAll();
    }
}

可以随时进行修改,或者需要任何帮助我共同完成工作的东西.

Again feel free to modify or whatever is needed to help me to get something together.

非常感谢您的帮助

推荐答案

当我开始使用存储库和工作单元模式时,我使用的实现类似于此处(我强烈建议您通过这些链接).

When I started with repository and unit of work patterns I used the implementation similar to this (it is for ObjectContext API but converting it to DbContext API is simple). We used that implementation with MOQ and Unity without any problems. By the time implementations of repository and unit of work have evolve as well as the approach of injecting. Later on we found that whole this approach has serious pitfalls but that was alredy discussed in other questions I referenced here (I highly recommend you to go through these links).

令人惊讶的是,您正在评估EFv4.1,重点是模拟和单元测试,同时定义了根本无法进行单元测试(带有模拟)的服务方法.服务方法的主要问题是您没有将存储库/上下文作为依赖项传递,因此无法模拟它.测试服务且不使用真实存储库的唯一方法是使用某些

It is very surprising that you are evaluating the EFv4.1 with high emphasis on mocking and unit testing and in the same time you defined service method which is not unit-testable (with mocking) at all. The main problem of you service method is that you are not passing repository/context as dependency and because of that you can't mock it. The only way to test your service and don't use the real repository is using some very advanced approach = replacing mocking and MOQ with detouring (for example Moles framework).

首先,您必须做的是将服务代码替换为:

First what you must do is replacing your service code with:

public class StudentService : IStudentService
{
    private readonly IStudentRepository _studentRepository;

    public StudentService(IStudentRepository studentRepository)
    {
        _studentRepository = studentRepository;
    }

    public IEnumerable<Student> GetAll()
    {
         return _studentRepository.GetAll().ToList();
    }
}

顺便说一句.这绝对是无用的代码,也是傻傻的分层的示例,它没有提供任何有用的功能.仅包装对存储库的调用仅表明完全不需要服务,也不需要对该方法进行单元测试.这里的重点是GetAll方法的集成测试.

Btw. this is absolutely useless code and example of silly layering which doesn't offer any useful functionality. Just wrapping the call to repository only shows that service is not needed at all as well as unit testing this method is not needed. The main point here is integration test for GetAll method.

无论如何,如果您想将这种方法与最小起订量结合在一起,您将这样做:

Anyway if you want to unit thest such method with MOQ you will do:

[TestClass]
public class StudentsServiveTest
{
    private Mock<IRespository<Student>> _repo;

    [TestInitialize]
    public void Init()
    {
        _repo = new Mock<IRepository<Student>>();
        _repo.Setup(r => r.GetAll()).Returns(() => new Student[] 
            { 
                new Student { StudentId = 1, Name = "A", Surname = "B" },
                new Student { StudentId = 2, Name = "B", Surname = "C" }
            });
    }

    [TestMethod]
    public void ShouldReturnAllStudents()
    {
        var service = new StudentsService(_repo.Object);
        var data = service.GetAll();
        _repo.Verify(r => r.GetAll(), Times.Once());

        Assert.IsNotNull(data);
        Assert.AreEqual(2, data.Count);
    }
}

这篇关于似乎无法添加EF CodeFirst 4.1.可以帮助任何人吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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