Moq 设置添加相同 "Filter" 而不是覆盖
Moq Setup Adding With Same "Filter" instead of overwriting
我正在尝试在 Moq 中模拟 DbSet<>,我可以在其中添加到 DbSet<> 中的实体列表。换句话说,一个可变的 DbSet<>.
我为此编写了一些扩展方法,但已将问题提炼成一个测试。
我认为 在 Moq 中,如果您使用相同的参数设置相同的调用(过滤器),设置是否被替换?
但是,下面的单元测试显示它已添加?
见'below throws "Expected collection to contain 1 item(s), but found 2."'
[Fact]
public void Add2Test()
{
var contextMock = new Mock<IDbContext>();
List<MyEntity> data = new List<MyEntity>(){new MyEntity()};
var queryable = data.AsQueryable();
var mockDbSet = new Mock<DbSet<MyEntity>>();
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(0);
contextMock.Setup(x => x.Set<MyEntity>()).Returns(mockDbSet.Object);
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
// let's do it again
data = new List<MyEntity>() { new MyEntity() };
queryable = data.AsQueryable();
mockDbSet = new Mock<DbSet<MyEntity>>();
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
contextMock.Setup(x => x.Set<MyEntity>()).Returns(mockDbSet.Object);
// below throws "Expected collection to contain 1 item(s), but found 2."
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
}
根据我对 EntityFrameworkCore.Testing, MemoryCache.Testing 等编写库的观察,Moq 没有 replace/override 相同的现有设置。
虽然这是一个 Moq 实现细节,但目前如果您多次设置相同的表达式,将使用最后添加的设置。
void Main()
{
var mock = new Mock<IFoo>();
mock.Setup(x => x.Bar()).Returns("A");
mock.Setup(x => x.Bar()).Returns("B");
var mocked = mock.Object;
Console.WriteLine(mocked.Bar());
Console.WriteLine(mock.Setups.Select(x => x.ToString()));
}
public interface IFoo
{
public string Bar();
}
我正在尝试在 Moq 中模拟 DbSet<>,我可以在其中添加到 DbSet<> 中的实体列表。换句话说,一个可变的 DbSet<>.
我为此编写了一些扩展方法,但已将问题提炼成一个测试。
我认为 在 Moq 中,如果您使用相同的参数设置相同的调用(过滤器),设置是否被替换?
但是,下面的单元测试显示它已添加?
见'below throws "Expected collection to contain 1 item(s), but found 2."'
[Fact]
public void Add2Test()
{
var contextMock = new Mock<IDbContext>();
List<MyEntity> data = new List<MyEntity>(){new MyEntity()};
var queryable = data.AsQueryable();
var mockDbSet = new Mock<DbSet<MyEntity>>();
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(0);
contextMock.Setup(x => x.Set<MyEntity>()).Returns(mockDbSet.Object);
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
// let's do it again
data = new List<MyEntity>() { new MyEntity() };
queryable = data.AsQueryable();
mockDbSet = new Mock<DbSet<MyEntity>>();
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Provider).Returns(queryable.Provider);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.Expression).Returns(queryable.Expression);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
mockDbSet.As<IQueryable<MyEntity>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator());
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
contextMock.Setup(x => x.Set<MyEntity>()).Returns(mockDbSet.Object);
// below throws "Expected collection to contain 1 item(s), but found 2."
contextMock.Setups.Where(s => s.Expression.ReturnType == typeof(DbSet<MyEntity>)).Should().HaveCount(1);
}
根据我对 EntityFrameworkCore.Testing, MemoryCache.Testing 等编写库的观察,Moq 没有 replace/override 相同的现有设置。
虽然这是一个 Moq 实现细节,但目前如果您多次设置相同的表达式,将使用最后添加的设置。
void Main()
{
var mock = new Mock<IFoo>();
mock.Setup(x => x.Bar()).Returns("A");
mock.Setup(x => x.Bar()).Returns("B");
var mocked = mock.Object;
Console.WriteLine(mocked.Bar());
Console.WriteLine(mock.Setups.Select(x => x.ToString()));
}
public interface IFoo
{
public string Bar();
}