C# 在.NET Core中使用xUnit、Moq和repository模式测试服务层
我正在构建一个简单的.NETCoreWebAPI应用程序,其中有一个后台任务,可以从网站下载一些CSV文件,并将它们保存到数据库中(使用EFCore)。另一个后台任务将负责处理它们。 这只是一个演示应用程序,让我熟悉.NET核心Web Api、EF核心、Moq、xUnit和存储库/服务/工作单元模式 我已经编写了业务逻辑,它运行良好,但现在我还想进行测试 这是我为了测试排队功能而编写的测试:它非常简单。我检查文件是否已经排队(针对特定日期),如果没有,我将其排队C# 在.NET Core中使用xUnit、Moq和repository模式测试服务层,c#,unit-testing,.net-core,moq,xunit,C#,Unit Testing,.net Core,Moq,Xunit,我正在构建一个简单的.NETCoreWebAPI应用程序,其中有一个后台任务,可以从网站下载一些CSV文件,并将它们保存到数据库中(使用EFCore)。另一个后台任务将负责处理它们。 这只是一个演示应用程序,让我熟悉.NET核心Web Api、EF核心、Moq、xUnit和存储库/服务/工作单元模式 我已经编写了业务逻辑,它运行良好,但现在我还想进行测试 这是我为了测试排队功能而编写的测试:它非常简单。我检查文件是否已经排队(针对特定日期),如果没有,我将其排队 [Fact] p
[Fact]
public void TestQueueFileForProcessingWhenNotYetQueued()
{
string alreadyQueuedFile = "Estrazione del 2019-01-02";
var mockUnitOfWork = new Mock<IUnitOfWork>();
var gasStationExternalFileRepository = new Mock<IGasStationExternalFileRepository>();
var service = new GasStationExternalFileService(mockUnitOfWork.Object, gasStationExternalFileRepository.Object);
gasStationExternalFileRepository.Setup(x => x.HasFileAlreadyBeenQueued(new DateTime(2019, 01, 02))).Returns(false);
var result = service.QueueFileForProcessing(Encoding.UTF8.GetBytes(alreadyQueuedFile));
Assert.True(result, "Object has been queued now");
var expectedFile = gasStationExternalFileRepository.Object.SingleOrDefault(x => x.ReferenceDate.Date == new DateTime(2019, 01, 02));
Assert.NotNull(expectedFile);
Assert.Equal(Encoding.UTF8.GetBytes(alreadyQueuedFile), expectedFile.Content);
Assert.Null(expectedFile.ProcessingDate);
Assert.Equal(Core.Reference.ProcessingStatus.Queued, expectedFile.ProcessingStatus);
Assert.Equal(new DateTime(2019, 01, 02), expectedFile.ReferenceDate);
}
我在等那个文件
var expectedFile = gasStationExternalFileRepository.Object.SingleOrDefault(x => x.ReferenceDate.Date == new DateTime(2019, 01, 02));
不为空。但它总是空的
我错过了什么
编辑:这是正在测试的主题
public class GasStationExternalFileRepository : Repository<GasStationsExternalFile, DbContext>, IGasStationExternalFileRepository
{
public GasStationExternalFileRepository(DbContext context) : base(context)
{
}
public bool HasFileAlreadyBeenQueued(DateTime referenceDate)
{
return Entities.Where(x => x.ReferenceDate.Date == referenceDate).Select(x => x.Id).Any();
}
}
public abstract class Repository<TEntity, TContext> : IRepository<TEntity>
where TEntity : class, IEntity
where TContext : DbContext
{
public Repository(TContext context)
{
Entities = context.Set<TEntity>();
}
protected DbSet<TEntity> Entities { get; }
public TEntity Get(Guid id)
{
return Entities.Find(id);
}
public IEnumerable<TEntity> GetAll()
{
return Entities.ToList();
}
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return Entities.Where(predicate);
}
public TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate)
{
return Entities.SingleOrDefault(predicate);
}
public void Add(TEntity entity)
{
Entities.Add(entity);
}
public void AddRange(IEnumerable<TEntity> entities)
{
Entities.AddRange(entities);
}
public void Remove(TEntity entity)
{
Entities.Remove(entity);
}
public void RemoveRange(IEnumerable<TEntity> entities)
{
Entities.RemoveRange(entities);
}
}
公共类GassStationExternalFileRepository:Repository,IGasStationExternalFileRepository
{
public GasStationExternalFileRepository(DbContext上下文):基础(上下文)
{
}
public bool HasFileAlreadyBeenQueued(日期时间引用日期)
{
返回Entities.Where(x=>x.ReferenceDate.Date==ReferenceDate).Select(x=>x.Id).Any();
}
}
公共抽象类存储库:IRepository
其中tenty:类,tenty
其中TContext:DbContext
{
公共存储库(TContext上下文)
{
Entities=context.Set();
}
受保护的数据库集实体{get;}
公共权限获取(Guid id)
{
返回实体。查找(id);
}
公共IEnumerable GetAll()
{
返回实体。ToList();
}
公共IEnumerable查找(表达式谓词)
{
返回实体。其中(谓词);
}
公共TEntity SingleOrDefault(表达式谓词)
{
返回实体。SingleOrDefault(谓词);
}
公共无效添加(TEntity实体)
{
实体。添加(实体);
}
公共void AddRange(IEnumerable实体)
{
实体。添加范围(实体);
}
公共无效删除(TEntity实体)
{
实体。移除(实体);
}
公共无效删除范围(IEnumerable实体)
{
实体。删除范围(实体);
}
}
gasStationExternalFileRepository
是一个模拟文件。测试返回null是有意义的,因为它没有设置为包含任何数据。测试模拟对象也是没有意义的。显示被测试的主题以及您实际想要实现的内容。请参阅最后一个编辑我想要实现的是:调用gasStationExternalFileRepository.object.SingleOrDefault(x=>x.ReferenceDate.Date==new DateTime(2019,01,02));返回我在我的业务逻辑中添加到它的对象。您应该只测试GasStationExternalFileService
的方法/属性。您的GassStationExternalFileRepository
不是一个存储库,它只是一个存根对象,以满足您的服务对IGasStationExternalFileRepository
的需求。只要假设.Add(file)
在单元测试中起作用,因为这不是测试的内容。存储库的实现应该有自己的单元测试。
public class GasStationExternalFileRepository : Repository<GasStationsExternalFile, DbContext>, IGasStationExternalFileRepository
{
public GasStationExternalFileRepository(DbContext context) : base(context)
{
}
public bool HasFileAlreadyBeenQueued(DateTime referenceDate)
{
return Entities.Where(x => x.ReferenceDate.Date == referenceDate).Select(x => x.Id).Any();
}
}
public abstract class Repository<TEntity, TContext> : IRepository<TEntity>
where TEntity : class, IEntity
where TContext : DbContext
{
public Repository(TContext context)
{
Entities = context.Set<TEntity>();
}
protected DbSet<TEntity> Entities { get; }
public TEntity Get(Guid id)
{
return Entities.Find(id);
}
public IEnumerable<TEntity> GetAll()
{
return Entities.ToList();
}
public IEnumerable<TEntity> Find(Expression<Func<TEntity, bool>> predicate)
{
return Entities.Where(predicate);
}
public TEntity SingleOrDefault(Expression<Func<TEntity, bool>> predicate)
{
return Entities.SingleOrDefault(predicate);
}
public void Add(TEntity entity)
{
Entities.Add(entity);
}
public void AddRange(IEnumerable<TEntity> entities)
{
Entities.AddRange(entities);
}
public void Remove(TEntity entity)
{
Entities.Remove(entity);
}
public void RemoveRange(IEnumerable<TEntity> entities)
{
Entities.RemoveRange(entities);
}
}