MZG
MZG

Reputation: 335

Test service class using moq in asp.net

I have a service class like this:

public class CategoryService: ICategoryService
{
    private myContext _context;
    public CategoryService(myContext context)
    {
         _context = context;
    }
        
    public async Task<List<CategoryDTO>> GetCategories()
    {  
            
        return (await _context.Categories.ToListAsync()).Select(c => new CategoryDTO
        {
              CategoryId = c.CategoryId, 
              CategoryName = c.CategoryName
                
        }).ToList();
    }
}

My context looks like this:

public DbSet<Category> Categories {get;set;} 

My unit test for GetCategories() is:

[Fact]
public void TestGetCategories()
{      
    //Arrange
    Mock <myContext> moq = new Mock <myContext>();
 
    var moqSet = new Mock<DbSet<Category>>();
             
    moq.Setup(m => m.Categories).Returns(moqSet.Object);
                
    CategoryService service = new CategoryService(moq.Object);

    //Act
    var result = service.GetCategories();

    //Assert
    Assert.NotNull(result);

 }

But I am getting error for my unit test. It says:

System.NotSupportedException : Unsupported expression: m => m.Categories

Can someone help me to fix the Setup part?

Upvotes: 3

Views: 143

Answers (2)

MZG
MZG

Reputation: 335

I finally could figure it out. As @PeterCsala mentioned, we can use "EntityFrameworkCore3Mock" You can find it here: https://github.com/huysentruitw/entity-framework-core3-mock

My unit test looks like this:

public DbContextOptions<ShoppingCartContext> dummyOptions { get; } = new DbContextOptionsBuilder<ShoppingCartContext>().Options;

[Fact]
public async Task TestGetCategories()
{
     //Arrange
     var dbContextMoq = new DbContextMock<ShoppingCartContext>(dummyOptions);

     //Create list of Categories
     dbContextMoq.CreateDbSetMock(x => x.Categories, new[]
     {
         new Category { CategoryId = 1, CategoryName = "Items" },
         new Category { CategoryId = 2, CategoryName = "Fruits" }
     });

     //Act
     CategoryService service = new CategoryService(dbContextMoq.Object);
     var result = await service.GetCategories();

     //Assert
     Assert.NotNull(result);

}

Upvotes: 2

Athanasios Kataras
Athanasios Kataras

Reputation: 26362

You cannot use Moq with non overrideable properties. It needs to be either abstract or virtual and that's why you get the error.

Change the dbcontext property Categories to virtual and try again.

public virtual DbSet<Category> Categories {get;set;}

P.s. you don't need to do this when you mock interface methods, because they are inherently overridable.

Upvotes: 1

Related Questions