【问题标题】:Test service class using moq in asp.net在 asp.net 中使用 moq 测试服务类
【发布时间】:2021-01-25 15:42:49
【问题描述】:

我有一个这样的服务类:

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();
    }
}

我的上下文如下所示:

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

我对@9​​87654325@ 的单元测试是:

[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);

 }

但是我的单元测试出错了。它说:

System.NotSupportedException:不支持的表达式:m => m.Categories

有人可以帮我修复设置部分吗?

【问题讨论】:

  • 您是否考虑过使用以下 nuget 包之一来减轻 EF 模拟的痛苦:EntityFrameworkCore.TestingEntityFrameworkCore3Mock?作为先决条件,请将您的DbSet 属性设为virtual
  • 谢谢你的回答,我试试看。
  • @PeterCsala 非常感谢您的帮助。 “EntityFrameworkCore3Mock”真的很有帮助。

标签: c# asp.net unit-testing moq xunit


【解决方案1】:

我终于明白了。 正如@PeterCsala 提到的,我们可以使用“EntityFrameworkCore3Mock” 你可以在这里找到它:https://github.com/huysentruitw/entity-framework-core3-mock

我的单元测试如下所示:

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);

}

【讨论】:

  • 很高兴它对您有所帮助。功劳归于@huysentruitw。
【解决方案2】:

您不能将 Moq 与不可覆盖的属性一起使用。它必须是抽象的或虚拟的,这就是您收到错误的原因。

dbcontext 属性Categories 更改为虚拟并重试。

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

附:模拟接口方法时不需要这样做,因为它们本质上是可覆盖的。

【讨论】:

  • 感谢您的回答,但我收到另一个错误消息:“InvalidProxyConstructorArgumentsException:无法实例化类代理”
  • 你得到这个的原因是 Moq 需要一个可访问的构造函数来创建模拟实例。如果您没有无参数构造函数,则需要在创建模拟时提供构造函数参数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多