如何解决执行xUnit Moq测试以创建记录并将其保存到DbContext
我正在编写用.NET CORE 3.1编写的Web API应用程序的测试。我正在使用xUnit,AutoFixture和Moq进行测试。我有一个使用Entity Framework / DbContext在数据库中创建新学校实例的类。我的问题是如何模拟dbContext并保存更改,此外我的School DataModel还有一个:与SchoolBranch DataModel的许多关系。我已遵循本教程http://www.c-jump.com/CIS77/CPU/x86/X77_0060_mod_reg_r_m_byte.htm
错误
Message:
Moq.MockException :
Expected invocation on the mock once,but was 0 times: m => m.Add<School>(It.IsAny<School>())
Performed invocations:
Mock<SchoolDbContext:1> (m):
No invocations performed.
Stack Trace:
Mock.Verify(Mock mock,LambdaExpression expression,Times times,String failMessage)
Mock`1.Verify[TResult](Expression`1 expression,Times times)
CreateSchoolCommandTest.ExecuteMethod_ShouldReturnNewGuidId_IfSuccess() line 50
学校
public class School
{
public School()
{
this.SchoolBranches = new HashSet<SchoolBranch>();
}
public Guid SchoolID { get; set; }
public string Name { get; set; }
public ICollection<SchoolBranch> SchoolBranches { get; set; }
}
SchoolBranch
public class SchoolBranch
{
public SchoolBranch()
{
}
public Guid SchoolBranchID { get; set; }
public Guid SchoolID { get; set; }
public string Address { get; set; }
public int PhoneNumber { get; set; }
public School School { get; set; }
}
CreateSchool类
public class CreateSchool : BaseCommand<Guid>,ICreateSchool
{
public SchoolDto SchoolDtos { get; set; }
public CreateSchool(IAppAmbientState appAmbient) : base(appAmbient) { }
public override Guid Execute()
{
try
{
var schoolId = Guid.NewGuid();
List<SchoolBranch> schoolBranches = new List<SchoolBranch>();
foreach(var item in SchoolDtos.SchoolBranchDtos)
{
schoolBranches.Add(new SchoolBranch()
{
SchoolBranchID = Guid.NewGuid(),SchoolID = schoolId,Address = item.Address,PhoneNumber = item.PhoneNumber
});
}
var school = new School()
{
SchoolID = schoolId,Name = SchoolDtos.Name,SchoolBranches = schoolBranches
};
schoolDbContext.Schools.Add(school);
schoolDbContext.SaveChanges();
return school.SchoolID;
}
catch(Exception exp)
{
appAmbientState.Logger.LogError(exp);
throw;
}
}
}
测试类
public class CreateSchoolCommandTest
{
private readonly ICreateSchool sut;
private readonly Mock<IAppAmbientState> appAmbientState = new Mock<IAppAmbientState>();
[Fact]
public void ExecuteMethod_ShouldReturnNewGuidId_IfSuccess()
{
//Arrange
var fixture = new Fixture();
var schoolDtoMock = fixture.Create<SchoolDto>();
var schoolDbSetMock = new Mock<DbSet<School>>();
var schoolBranchDbSetMock = new Mock<DbSet<SchoolBranch>>();
var schoolDbContextMock = new Mock<SchoolDbContext>();
//schoolDbSetMock.Setup(x => x.Add(It.IsAny<School>())).Returns((School s) => s); // this also did not work
schoolDbContextMock.Setup(m => m.Schools).Returns(schoolDbSetMock.Object);
//Act
sut.SchoolDtos = schoolDtoMock;
var actualDataResult = sut.Execute();
// Assert
Assert.IsType<Guid>(actualDataResult);
schoolDbContextMock.Verify(m => m.Add(It.IsAny<School>()),Times.Once());
schoolDbContextMock.Verify(m => m.SaveChanges(),Times.Once());
}
BaseCommand(在此处创建了DbContext)
public abstract class BaseCommand<T>
{
protected SchoolDbContext schoolDbContext;
protected IAppAmbientState appAmbientState { get; }
public BaseCommand(IAppAmbientState ambientState)
{
this.schoolDbContext = new SchoolDbContext();
this.appAmbientState = ambientState;
}
public abstract T Execute();
}
解决方法
针对修复错误
您犯了一个小错误。插入
schoolDbContextMock.Verify(m => m.Add(It.IsAny<School>()),Times.Once());
schoolDbContextMock.Verify(m => m.SaveChanges(),Times.Once());
您应该拥有
schoolDbSetMock.Verify(m => m.Add(It.IsAny<School>()),Times.Once());
因为您在Add()
而不是schoolDbContext.Schools
上使用方法schoolDbContext
用于注入dbContext
您的BaseCoommand类构造函数应如下所示:
public BaseCommand(IAppAmbientState ambientState,SchoolDbContext schoolDbContext)
{
this.schoolDbContext = schoolDbContext;
this.appAmbientState = ambientState;
}
您的CreateSchool类构造函数:
public CreateSchool(IAppAmbientState appAmbient,SchoolDbContext schoolDbContext) : base(appAmbient,schoolDbContext) { }
接下来在测试中,您应该像这样在测试中初始化CreateSchool
:
var sut = new CreateSchool(ambientState,schoolDbContextMock.Object);
它将起作用
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。