模拟 FindAsync 方法

3
我使用以下代码模拟了FindAsync:

var brands = new Mock<DbSet<Brand>>();
ConfigureTheDbSet(brands, brandData);
brands.Setup(b => b.FindAsync(It.IsAny<object[]>()))    //substitution of the .SelectAsync(id) method
    .Returns<object[]>(ids => brands.Object.FirstOrDefaultAsync(b => b.BrandId == (int) ids[0]));

在我为上下文添加AsNoTracking的模拟之前,它一直运行正常:

var mockContext = new Mock<ReportDbContext>();
mockContext.Setup(m => m.Set<Brand>()).Returns(brands.Object);
mockContext.Setup(m => m.Set<Brand>().AsNoTracking()).Returns(brands.Object);

FindAsync返回null。为了使其正常工作,我添加了以下模拟:

mockContext.Setup(m => m.Set<Brand>().FindAsync(It.IsAny<object[]>()))
    .Returns<object[]>(async d => await brands.Object.FindAsync(d));

有人知道为什么会发生这种情况吗?
4个回答

3

我认为你应该模拟接口,例如IBrandRepository。否则模拟的意义何在?- 你可以只创建一个类实例,调用FindAsync()并像往常一样断言结果。

以下是我如何使用Moq和接口,例如repo接口:

// arrange
var mockRepo = new Mock<IBrandRepository>();
mockRepo.Setup(o => o.FindAsync(It.IsAny<string>())).ReturnsAsync(new Brand[] { ... });

var someClass = new SomeClass(IBrandRepository); // someClass that use IBrandRepository

// act
string search = "brand1 brand2"; // what the user searches for   
var results = someClass.FindBrands(searchText) // internally calls IBrandRepository.FindAsync()

// assert
// Assert.AreEqual(results.Count(), ...

这没有意义,因为我模拟了传递给服务的上下文,它定义了服务的行为。 - Dmitry Shevchuk

1

迪米特里,我知道已经过了几年。我刚遇到同样的问题,这是我解决它的方法。

this.mocContext.Setup(x => x.Company.FindAsync(It.IsAny<string> 
())).Returns(Task.FromResult(this.GetCompanyList().SingleOrDefault(x => 
x.CompanyCode.Equals("M5QoKF4AS0"))));

这里的mocContext是我模拟的数据库,Company是我想要在其上执行FindAsync操作的表格,而Get CompanyList则只是从数据中获取填充了表格的内容。希望这能有所帮助。


0

我通过使用.Where(entity => entity.PrimaryKey == key).FirstOrDefaultAsync()代替.FindAsync(key)来规避这种嘲弄,因为FirstOrDefaultAsync不需要单独的嘲弄,并且两种方法之间的逻辑也相同。


0

对于任何遇到困难的人,这里有另一种方法:

首先:创建 DbContext 和 DbSet 的模拟,例如:

private static readonly Mock<ApplicationDbContext> mockDbContext = new();
private static readonly Mock<DbSet<Game>> mockGameSet = new();

第二步:设置模拟的DbContext中DbSet的Get方法,如下所示:

mockDbContext.SetupGet(_ => _.Games).Returns(mockGameSet.Object);

第三步,也是最后一步:在模拟的DbSet中设置FindAsync()如下:

mockGameSet.Setup(x => x.FindAsync(It.IsAny<int>())).ReturnsAsync(game);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接