【发布时间】:2021-10-15 03:13:56
【问题描述】:
我有以下场景
public long Update(ExpenseViewModel updateModel, string einterpriseid)
{
long internId;
ExpenseReq expenseRequest = GetReqById(updateModel.Id);
if (expenseRequest != null)
{
int DraftStatusID = GetStatusID("Draft");
int PendingStatusID = GetStatusID("Pending Approval");
}
}
public ExpenseReq GetReqById(int id)
{
return _db.ExpRequest
.Include(x => x.Profile).AsNoTracking()
.Include(x => x.ExpReqStatus).AsNoTracking()
.Include(x => x.AdditionalDetails)
.ThenInclude(x => x.ExpenseReqTravelDetails).AsNoTracking()
.Include(x => x.AddDetail)
.ThenInclude(x => x.ExpRejReason).AsNoTracking()
.Include(x => x.AdditionalDetails)
.ThenInclude(x => x.ExpenseTypes).AsNoTracking()
.Include(x => x.AdditionalDetails)
.ThenInclude(x => x.ExpReqApprover).AsNoTracking()
.Include(x => x.Comp).AsNoTracking()
.Where(x => x.Id == id).FirstOrDefault();
}
当我对Update 执行单元测试时,GetReqById 函数总是返回我null,因为没有满足 if 条件并且内部 if 条件行覆盖没有发生。我想在 if 条件下获得代码覆盖率。如何为它编写单元测试?
我在下面尝试过:
[Fact]
public void Should_Update()
{
var options = new DbContextOptionsBuilder<dbContextobj>().UseInMemoryDatabase(databaseName: "fakedb").Options;
using (var context = new dbContextobj(options))
{
var controller = new ExpenseRequestService(context);
var result = controller.Update(expenseRequestUpdateViewModel, "test");
Assert.Equal(0, result);
}
}
这工作正常,但 GetReqById 没有被覆盖。请帮我提供一些示例代码。
谢谢。
【问题讨论】:
-
如果您将
GetReqById移动到另一个类和接口中,然后将该接口注入到对象的构造函数中,那么您的测试代码可以“模拟”该接口以使该方法调用返回您想要的任何内容。 -
感谢您的回复。这里的问题是代码已经在生产中运行,现在对现有代码进行任何更改都将进行彻底的测试和所需的批准。所以我不想对现有的进行任何更改,并且不进行任何更改我想执行单元测试。
-
你使用
UseInMemoryDatabase意味着每次你运行项目时,据我所知,它都会创建新数据。因此,如果您真的要测试代码单元,您确实需要模拟数据库的返回,否则您将进行更多测试,那么您应该这样做。请记住,单元测试专注于测试方法而不是您的依赖项。 -
与问题无关,但我在源代码中注意到了一些东西。我不相信你应该在每个
Include上使用AsNoTracking()。AsNoTracking()将应用于父实体和所有子实体:stackoverflow.com/questions/42002540/asnotracking-and-include -
虽然我理解您不愿做出对您需要添加的测试而言并非绝对必要的更改,但当开发人员害怕重构代码时,这对我来说是一个危险信号。只是说。
标签: c# .net unit-testing asp.net-core-webapi xunit