拥有这样的C#代码,并尝试检查IsFailureProcessStatus方法以返回true。dapper类SqlMapper中的查询方法,该方法使用参数调用存储过程。
public class DatabaseManager : IDatabaseManager
{
private readonly SqlConnection CoreDbProcessesConnection;
private readonly SqlConnection HrReportDbConnection;
// there are other private fields with parameters and sql-procedures names
public DatabaseManager(IDbConnectionsProvider dbConnectionsProvider)
{
this.CoreDbProcessesConnection = dbConnectionsProvider.CoreDbProcessesConnection;
this.HrReportDbConnection = dbConnectionsProvider.HrReportDbConnection;
}
public List<CoreProcessStatusDto> GetProcessStatusIds(string ProcessName, DateTime dateTime)
{
var parameters = new DynamicParameters();
parameters.Add(processStatusProcedureParamName01, ProcessName);
parameters.Add(processStatusProcedureParamName02, dateTime);
var output = this.CoreDbProcessesConnection
.Query<CoreProcessStatusDto>(ProcessStatusProcedureName, parameters, commandType: CommandType.StoredProcedure).ToList();
return output;
}
public bool IsFailureProcessStatus(StepDto.StepDescription step, DateTime dateTime)
{
bool isStepFailure = true;
Stopwatch doStepUntil = new Stopwatch();
doStepUntil.Start();
while (doStepUntil.Elapsed < TimeSpan.FromSeconds(step.SecondsElapsed))
{
step.StatusTypesList = this.GetProcessStatusIds(step.ProcessName, dateTime);
var statusTypesStepSelection = step.StatusTypesList.Select(st => st.ProcessStatusTypeId).ToList();
//...
// if...else operations here to make step true or false
//...
}
doStepUntil.Stop();
return isStepFailure;
}
}
单元测试代码位于以下位置:
[TestClass]
public class DatabaseManagerTests
{
[TestMethod]
public void IsFailureProcessStatus_ReturnTrue()
{
DateTime dateTime = DateTime.Now;
StepDto step1Dto = new StepDto()
{
JobName = "ETL - HR - FilesImport - Reporting",
JobStepName = "RunMCP_User_Department_Map",
Step = new StepDto.StepDescription()
{
StatusTypesList = new List<CoreProcessStatusDto>(),
ProcessName = "HR_User_Department_Map_Import",
SecondsElapsed = 30,
PackageCount = 2
}
};
using (var mock = AutoMock.GetLoose())
{
var dbProviderMock = new Mock<IDbConnectionsProvider>(MockBehavior.Loose);
var dbMock = new Mock<DatabaseManager>(dbProviderMock.Object);
mock.Mock<IDatabaseManager>()
.Setup(p => p.GetProcessStatusIds(step1Dto.Step.ProcessName, dateTime))
.Returns(GetCoreProcessesStatusIdsTest());
var sut = mock.Provide(dbMock.Object);
//var sut = mock.Create<DatabaseManager>();
var actual = sut.IsFailureProcessStatus(step1Dto.Step, dateTime);
Assert.IsTrue(actual);
}
}
private List<CoreProcessStatusDto> GetCoreProcessesStatusIdsTest()
{
var output = new List<CoreProcessStatusDto>()
{
new CoreProcessStatusDto() { ProcessStatusTypeId = 3 },
new CoreProcessStatusDto() { ProcessStatusTypeId = 2 }
};
return output;
}
}
我尝试将GetProcessStatusIds方法设置为在调用sut.IsFailureProcessStatus代码时返回值,但是在调试其运行GetProcessStatusIds并尝试调用Query方法时抛出NullReferenceException异常。
Test Name: IsFailureProcessStatus_ReturnTrue
Test Outcome: Failed
Result StackTrace:
at Dapper.SqlMapper.<QueryImpl>d__140`1.MoveNext() in C:\projects\dapper\Dapper\SqlMapper.cs:line 1066
at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
at Dapper.SqlMapper.Query[T](IDbConnection cnn, String sql, Object param, IDbTransaction transaction, Boolean buffered, Nullable`1 commandTimeout, Nullable`1 commandType) in C:\projects\dapper\Dapper\SqlMapper.cs:line 721
at ATP.HR.FolderWatcher.Service.Managers.DatabaseManager.GetProcessStatusIds(String ProcessName, DateTime dateTime) in C:\HOME\anatolii.dmitryv\src\HRM\hr-folder-watcher-service\ATP.HR.FolderWatcher.Service\Managers\DatabaseManager.cs:line 46
at ATP.HR.FolderWatcher.Service.Managers.DatabaseManager.IsFailureProcessStatus(StepDescription step, DateTime dateTime) in C:\HOME\anatolii.dmitryv\src\HRM\hr-folder-watcher-service\ATP.HR.FolderWatcher.Service\Managers\DatabaseManager.cs:line 83
at ATP.HR.FolderWatcher.Service.Test.DatabaseManagerTests.IsFailureProcessStatus_ReturnTrue() in C:\HOME\anatolii.dmitryv\src\HRM\hr-folder-watcher-service\ATP.HR.FolderWatcher.Service.Tests\DatabaseManagerTests.cs:line 57
Result Message:
Test method ATP.HR.FolderWatcher.Service.Test.DatabaseManagerTests.IsFailureProcessStatus_ReturnTrue threw exception:
System.NullReferenceException: Object reference not set to an instance of an object.
在模拟这种方法时,我到底做错了什么?我怎么说可以测试不要运行此GetProcessStatusIds并仅返回硬编码值?
尝试使用此方法,但对我不起作用:
using (var mock = AutoMock.GetLoose())
{
mock.Mock<IDatabaseManager>()
.Setup(p => p.GetProcessStatusIds(It.IsAny<string>(), It.IsAny<DateTime>()))
.Returns(GetCoreProcessesStatusIdsTest());
var sut = mock.Create<DatabaseManager>();
var actual = sut.IsFailureProcessStatus(step1Dto.Step, dateTime);
Assert.IsTrue(actual);
}
进行单元测试时的第一件事是定义测试的目标,在您要测试的内部逻辑IsFailureProcessStatus
的问题中,这里的问题是您模拟IDatabaseManager
具有该IsFailureProcessStatus
方法的接口。
您不需要那种模拟IDatabaseManager
,只有当它用作其他客户服务的提供者时,才需要模拟。
并且因为您正在测试内部逻辑,所以IsFailureProcessStatus
您只需模拟和执行内部逻辑执行所需的设置方法,IDbConnectionsProvider
然后设置其方法即可CoreDbProcessesConnection
用于DatabaseManager
实际实例。
var dbProviderMock = new Mock<IDbConnectionsProvider>(MockBehavior.Loose);
dbProviderMock
.Setup(p => p.CoreDbProcessesConnection)
.Returns(new SqlConnection(...));
DatabaseManager databaseManager = new DatabaseManager(dbProviderMock.Object);
var actual = databaseManager.IsFailureProcessStatus(step1Dto.Step, dateTime);
Assert.IsTrue(actual);
我能理解您为什么错误地尝试了模拟GetProcessStatusIds
,但是由于我们拥有的真实实例DatabaseManager
,所以不需要使用它,因此您将仅模拟在执行过程中所需的依赖接口GetProcessStatusIds
,这就是为什么我们在这里不需要设置的原因的HrReportDbConnection
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句