具有此类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);
}
问题是您正在将特定值传递给Setup
方法。
在It.IsAny<string>()
方法中使用It.IsAny<DateTime>()
和Setup
:
mock.Mock<IDatabaseManager>()
.Setup(p => p.GetProcessStatusIds(It.IsAny<string>(), It.IsAny<DateTime>()))
.Returns(GetCoreProcessesStatusIdsTest());
如果仅需要接受特定值,则查看It.Is<T>
,例如:
It.Is<string>(s => !string.IsNullOrEmpty(s)) // not empty
It.Is<string>(s => s.StartsWith("HR_")) // starts with
It.Is<string>(s => s == "HR_User_Department_Map_Import") // equals
浏览Moq Quickstart guide了解更多信息。>>