简体   繁体   中英

How I unit test with Entity Framework and Moq when using a repository pattern with Interface?

I am new to testing and have been tasked at work to setup some simple CRUD test on a MVC EF Core Repository for some code that I wrote using MSTest.

One of get the methods eager loads a list using include, other wise it basic CRUD.

However I keep running into a discussion about either using in-memory db or mocking the ef core db and dbsets? What would be the best way to test an MVC EF Core Repository pattern with CRUD operations in a unit test?

 public DbSet<ResourceTags>? ResourceTags { get; set; }

 public class ResourceTags
 {

    [ForeignKey(nameof(ResourceRequest))]
    [Key]
    [Column(Order = 0)]
    public byte[] ResourceId { get; set; }

    [Key]
    [Column(Order = 1)]
    public string Tag { get; set; }

    public ResourceRequest ResourceRequest { get; set; }
}

   public ResourceTags? AddResourceTags(ResourceTags resourceTag)
   {
        try
        {
            var entity = this.prismContext.ResourceTags;

            if (entity != null)
            {
                var response = entity.Add(resourceTag);
                this.prismContext.SaveChanges();
                return response.Entity;
            }
        }
        catch
        {
            throw new Exception();
        }

        return null;
    }

    [TestMethod]
    public void AddResourceTagsSavesAResourceTagsViaContext()
    {
        Random rnd = new Random();
        var id = new byte[32];
        rnd.NextBytes(id);
        var text = "tagtext";
        string convertedId = Convert.ToBase64String(id);

        var mockResourceTag = new Mock<DbSet<ResourceTags>>();
        var mockPrismContext = new Mock<PrismContext>();

        mockPrismContext.Setup(m => m.ResourceTags).Returns(mockResourceTag.Object);

        var azureRepository = new AzureRepository(mockPrismContext.Object);
        var tag = new ResourceTags()
        {
            ResourceId = id,
            Tag = text,
        };

        var response = azureRepository.AddResourceTags(tag);
        Assert.IsNotNull(response);
    }

If you only use simple CRUD queries, and your queries do not depend on specific DB functions, eg, EF.Functions , then you should use InMemory Database , or SQLite with in-memory mode, which has better compatibility with real DBs.

Mocking the DbSet will result in poor testing because your test may pass but when EF tries to translate your LINQ query to SQL at runtime, it may throw an exception, and you want to ensure that your translations work.

A third option would be to test against a docker container, ie, if you use SQL Server, you test against an SQL Server instance running in docker. This way you remove any compatibility issues between DBs.

Sources:

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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