[英]System.NotSupportedException: Unsupported expression: p => (p.UserProfileId == 1)
[英]System.NotSupportedException : Unsupported expression: x => x
我目前正在尝试最小化我的Cafe
Get
方法,如果找不到咖啡馆 ID,该方法将抛出ArgumentNullexception
。
System.NotSupportedException: Unsupported expression: x => x.Cafe Non-overridable members (here: Context.get_Cafe) may not be used in setup / verification expressions.
发生这种情况是因为最小起订量无法处理其中一个设置表达式吗?
[Fact]
public async Task GetCafeByIdAsync_Should_Throw_ArgumentNullException()
{
var cafe = new List<Cafe>()
{
new Cafe { Name = "Hanna", CafeId = 1},
new Cafe { Name = "Bella", CafeId = 2 }
}.AsQueryable();
var mockSet = new Mock<DbSet<Cafe>>();
mockSet.As<IQueryable<Cafe>>().Setup(m => m.Provider).Returns(cafe.Provider);
mockSet.As<IQueryable<Cafe>>().Setup(m => m.Expression).Returns(cafe.Expression);
mockSet.As<IQueryable<Cafe>>().Setup(m => m.ElementType).Returns(cafe.ElementType);
mockSet.As<IQueryable<Cafe>>().Setup(m => m.GetEnumerator()).Returns(cafe.GetEnumerator());
var mapper = new MapperConfiguration(cfg =>
{
cfg.AddProfile(new AutoMapperProfile());
}).CreateMapper();
var contextMock = new Mock<Context>();
contextMock.Setup(x => x.Cafe).Returns(mockSet.Object); //failing here
var cafeService = new CafeService(contextMock.Object, mapper);
await Assert.ThrowsAsync<ArgumentNullException>(() => cafeService.Get(2));
}
public async Task<VersionResponse> Get(int cafeId)
{
var cafe = await _context.Cafe.Where(w => w.CafeId == cafeId).ToResponse().FirstOrDefaultAsync();
return new VersionResponse()
{
Data = cafe
};
}
Moq 依赖于能够创建覆盖属性的代理类。 Context.Cafe
不能被覆盖。 尝试将该属性声明为virtual
。
public virtual IDbSet<Cafe> Cafe { get; set; }
尝试在Set方法上设置模拟
public virtual DbSet<TEntity> Set<TEntity>() where TEntity : class;
在你的情况下
var contextMock = new Mock<Context>();
contextMock.Setup(x => x.Set<Cafe>()).Returns(mockSet.Object);
我有一个更好的集成测试方法 你可以使用事务回滚来进行这种类型的测试,这样你就可以在 Db 中做任何你想做的事,然后 Db 中的每一个动作都回到运行测试之前的最后一个 state
如果你使用 Ef,你可以将这个 class 添加到你的测试项目中并享受它
public abstract class PersistTest<T> : IDisposable where T : DbContext, new()
{
protected T DBContext;
private TransactionScope scope;
protected PersistTest()
{
scope = new TransactionScope();
DBContext = new T();
}
public void Dispose()
{
scope.Dispose();
DBContext.Dispose();
}
}
这个 class 帮助你编写更好的集成测试,
你的测试 class 应该继承自这个抽象 class 并将你的上下文 class 作为 DbContext 的实例传递
关于您的 Codd 的另一件事是您应该将 Logic 和 DataAccess 彼此分开
只需定义一个名为 ICofeeRepository 的接口并在其中采用您的方法您的代码打破单一责任原则
你的服务应该是这样的
public class CoffeService
{
//inject cafe repository ; _repo
public async Task<VersionResponse> Get(int cafeid)
{
var cafe = _repo.FindById(cafeid);
if (cafe == null)
throw Exception("");
//other wise .....
}
}
你的存储库应该是这样的
public interface ICafeRepository
{
Cafe Get(int cafeid);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.