简体   繁体   English

如何使用 moq 和 nunit 模拟 DbContext

[英]How to mock DbContext using moq and nunit

Please i am trying to mock a DbContext and write a test, from my test the error seems to come from the mocking of the DbContext.请我试图模拟一个 DbContext 并编写一个测试,从我的测试来看,错误似乎来自 DbContext 的 mocking。 maybe the way i set it up isn't correct.也许我设置的方式不正确。 can anyone spot the error or a better way of setting it up?任何人都可以发现错误或更好的设置方法吗? Thanks谢谢

Test and Setup: upVoteControllerTest.cs测试和设置:upVoteControllerTest.cs

[SetUp]
public void Setup()
{
    var config = new MapperConfiguration(cfg =>
    {
        cfg.AddProfile<MapperInitilizer>();
    });
    _realMapper = new Mapper(config);
    _upvotes = new Mock<IRepository<Upvote>>();
    _unitOfWork = new Mock<IUnitOfWork>();
    _unitOfWork.SetupGet(work => work.Upvotes).Returns(_upvotes.Object);
    _logger = new Mock<ILogger<UpvoteController>>();
    _mapper = new Mock<IMapper>();
    _context = new Mock<ApplicationDbContext>();
    _upvoteController = new UpvoteController(_context.Object, _mapper.Object,_unitOfWork.Object, _logger.Object);
    upvote_one = new Upvote()
    {
        Id = 1,
        UserId = "43434343434",
        TopicId = 1
    };
  
    upvote_two = new Upvote()
    {
        Id = 2,
        UserId = "65664535",
        TopicId = 2
    };

    user_one = new User()
    {
        Id = "43434343434",
        FirstName = "john",
        LastName = "doe",
        Email = "john@gmail.com",
        Photo = "hgghghg",
        PhoneNumber = "fgfffgfg"
    };

    List<User> expectedResult = new List<User> {user_one};
    var repo = new UserTestRepository();
}




[Test]
    public void GetAllUpVotes_SendRequest_ReturnListOfUpVotes()
    {
        List<Upvote> expectedResult = new List<Upvote> {upvote_one, upvote_two};
        var repo = new UpvoteTestRepository(expectedResult);
        var unitOfWork = new Mock<IUnitOfWork>();
        unitOfWork.SetupGet(work => work.Upvotes).Returns(repo);
        _upvoteController.GetUpvotes().GetAwaiter().GetResult();
        
        Assert.IsNotEmpty(repo.Source);
        CollectionAssert.AreEqual(expectedResult, repo.GetAll().GetAwaiter().GetResult());
    }

UpvoteController:投票控制器:

public UpvoteController(ApplicationDbContext context, IMapper mapper, 
            IUnitOfWork unitOfWork, ILogger<UpvoteController> logger)
        {
            _context = context;
            _mapper = mapper;
            _unitOfWork = unitOfWork;
            _logger = logger;
        }

        // GET: api/Upvote
        [HttpGet]
        public async Task<IActionResult> GetUpvotes()
        {
            try
            {
                var upvotes = await _unitOfWork.Upvotes.GetAll();
                var results = _mapper.Map<IList<UpvoteDTO>>(upvotes);
                return Ok(results);
            }
            catch (Exception e)
            {
                _logger.LogError(e, $"Something went wrong in the {nameof(GetUpvotes)}");
                return StatusCode(500, "Internal server error");
            }
        }

UpvoteTestRepository: UpvoteTestRepository:

public class UpvoteTestRepository : IRepository<Upvote>
{
    public IList<Upvote> Source;

    public UpvoteTestRepository(IList<Upvote> source)
    {
        Source = source;
    }

    public Task<Upvote> Get(Expression<Func<Upvote, bool>> expression, 
        Func<IQueryable<Upvote>, IIncludableQueryable<Upvote, object>> include = null)
    {
        
        IQueryable<Upvote> query = Source.AsQueryable();
        return Task.FromResult(query.FirstOrDefault(expression));
    }

    public Task<IList<Upvote>> GetAll(Expression<Func<Upvote, bool>> expression = null, Func<IQueryable<Upvote>, IOrderedQueryable<Upvote>> orderBy = null, Func<IQueryable<Upvote>, IIncludableQueryable<Upvote, object>> include = null, Expression<Func<Upvote, bool>> cat = null,
        int limit = 0)
    {
        
        return Task.FromResult(Source);
    }
}

Error:错误:

System.ArgumentException : Can not instantiate proxy of class: dotnetapp.Data.ApplicationDbContext.
    Could not find a parameterless constructor. (Parameter 'constructorArguments')
    ----> System.MissingMethodException : Constructor on type 'Castle.Proxies.ApplicationDbContextProxy' not found.
    at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyInstance(Type proxyType, List`1 proxyArguments, Type classToProxy, Object[] constructorArguments)
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] 

You can use in-memory db.您可以使用内存数据库。 But that's not such a good decision, there you can see why, but in general, if your app(db in general) is small it`s okay.但这不是一个很好的决定,在那里你可以明白为什么,但总的来说,如果你的应用程序(一般的数据库)很小,那没关系。

var options = new DbContextOptionsBuilder<MyDbContext>()
                      .UseInMemoryDatabase(Guid.NewGuid().ToString())
                      .Options;
var context = new MyDbContext(options);
context.Database.EnsureCreated();

In addition you can do it much better with EF Effort .此外,您可以使用EF Effort做得更好。 Which also use in-memory db, but efficient way这也使用内存数据库,但有效的方式

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM