我正在嘗試 Moq 一個同步程序,但我遇到了一個特定部分的問題。
在我的方法中,我嘗試最小起訂量,我執行以下操作:
public class SyncManager
{
private IPubHttpClient _pubHttpClient;
private ILogService _logService;
private Ilogger _logger;
public SyncManager(IPubHttpClient pubClient, ILogService logService ILogger<SyncManager> logger)
{
_pubHttpClient = pubClient;
_logService = logService;
_logger = logger;
}
public async Task Sync()
{
var syncStatus = SyncStatus.Error;
// get logs
var logs = await _logService.GetLogs();
foreach (var log in logs)
{
if (!string.IsNullOrEmpty(log.CostCode))
syncStatus = await GetAndSendCost(log);
elseif
syncStatus = await GetAndSendSort(log);
}
}
private async Task<SyncStatus> GetAndSendCost(Log log)
{
var cost = new Cost
{
CostCode = log.CostCode,
CostName = log.Description,
Active = log.Active
};
await _pubHttpClient.Push(new EventModel { Cost = cost, MessageType = log.Type.GetDescription() });
return SyncStatus.Success;
}
private async Task<SyncStatus> GetAndSendSort(Log log)
{
var sort = new Sort
{
SortCode = log.SortCode,
SortName = log.Description,
Active = log.Active
};
await _pubHttpClient.Push(new EventModel { Sort = sort, MessageType = log.Type.GetDescription() });
return SyncStatus.Success;
}
}
public class Log
{
public long Id { get; set; }
public string SortCode { get; set; }
public string CostCode { get; set; }
public string Description { get; set; }
public string Active { get; set; }
public AuditType Type { get; set; }
}
public class EventModel
{
public Cost Cost { get; set; }
public Sort Sort { get; set; }
public string MessageType { get; set; }
}
public enum AuditType
{
[Description("CREATE")]
Create = 0,
[Description("UPDATE")]
Update = 1,
[Description("DELETE")]
Delete = 2
}
public static class EnumExtensions
{
public static string GetDescription(this Enum enumValue)
{
return enumValue.GetType()
.GetMember(enumValue.ToString())
.First()
.GetCustomAttribute<DescriptionAttribute>()?
.Description ?? string.Empty;
}
}
我設定的測驗是這樣的:
public class SyncManagerTests
{
public readonly Mock<IPubHttpClient> _pubClientMock = new();
public readonly Mock<ILogService> _logServiceMock = new();
[Fact]
public async Task Should_Sync()
{
var mockedCost = new Cost { Active = Status.Active, CostCode = "0000", CostName = "UNIT TEST" };
var mockedSort = new Sort { Active = Status.Active, SortCode = "0001", SortName = "UNIT TEST" };
var mockedLogs = new List<Log> {
new Log { CostCode = mockedCost.CostCode, Description = mockedCost.CostName, Active = mockedCost.Active, Id = 1 },
new Log { SortCode = mockedSort.SortCode, Description = mockedSort.CostName, Active = mockedSort.Active, Id = 2 },
};
_logServiceMock.Setup(s => s.GetLogs()).ReturnsAsync(mockedLogs).Verifiable();
_pubClientMock.Setup(p => p.Push(It.Is<EventModel>(x => x.Cost == mockedCost && x.MessageType == "CREATE"))).Returns(Task.CompletedTask).Verifiable();
var syncManager = new SyncManager(_pubClientMock.Object, _logServiceMock.Object, Mock.Of<ILogger<SyncManager>>());
await syncManager.Sync();
_pubClientMock.Verify(p => p.Push(It.Is<EventModel>(
x => x.Cost.CostName == mockedCost.CostName
&& x.Cost.CostCode == mockedCost.CostCode
&& x.Cost.Active == mockedCost.Active
&& x.MessageType == "CREATE")));
}
}
當我運行這個測驗時,每段代碼都被正確呼叫,在除錯時我看到EventModel object正在使用正確的值創建。
但是,在我打電話的測驗中,_pubClientMock.Verify();我得到一個System.NullReferenceException: 似乎x.Cost這里是 NULL 。
知道為什么這個屬性會是 NULL 或者我在這里做錯了什么嗎?
所以再次迭代,實際上呼叫.Sync()并使用除錯器單步執行代碼可以完美地作業。這_pubClientMock.Verify是失敗的NullReferenceException.
uj5u.com熱心網友回復:
類似于已經提供的答案之一,我建議放松設定以避免使用It.IsAny. 這將允許測驗用例流向完成。
至于 Verification 中的 null 參考錯誤,因為更新后的示例會出現其中一個事件模型的Cost屬性值為 null 的情況,所以在驗證謂詞時需要檢查 null
[TestClass]
public class SyncManagerTests {
public readonly Mock<IPubHttpClient> _pubClientMock = new Mock<IPubHttpClient>();
public readonly Mock<ILogService> _logServiceMock = new Mock<ILogService>();
[Fact]
public async Task Should_Sync() {
var mockedCost = new Cost { Active = Status.Active, CostCode = "0000", CostName = "UNIT TEST" };
var mockedSort = new Sort { Active = Status.Active, SortCode = "0001", SortName = "UNIT TEST" };
var mockedLogs = new List<Log> {
new Log { CostCode = mockedCost.CostCode, Description = mockedCost.CostName, Active = mockedCost.Active, Id = 1 },
new Log { SortCode = mockedSort.SortCode, Description = mockedSort.SortName, Active = mockedSort.Active, Id = 2 },
};
_logServiceMock.Setup(s => s.GetLogs()).ReturnsAsync(mockedLogs);
_pubClientMock
.Setup(p => p.Push(It.IsAny<EventModel>())) //<-- NOTE THIS
.Returns(Task.CompletedTask);
var syncManager = new SyncManager(_pubClientMock.Object, _logServiceMock.Object, Mock.Of<ILogger<SyncManager>>());
await syncManager.Sync();
_pubClientMock.Verify(p => p.Push(It.Is<EventModel>(
x => x.Cost != null //<-- NOTE THE NULL CHECK
&& x.Cost.CostName == mockedCost.CostName
&& x.Cost.CostCode == mockedCost.CostCode
&& x.Cost.Active == mockedCost.Active
&& x.MessageType == "CREATE")));
}
}
uj5u.com熱心網友回復:
您能否提供有關通過 GetAndSendCost() 傳遞的 Log 的更多詳細資訊,也許問題來自該部分,您可以使用 It.IsAny<EventModel>()
// Arrange
Mock<IPubHttpClient> _pubClientMock = new Mock<IPubHttpClient>();
_pubClientMock.Setup(p => p.Push(It.IsAny<EventModel>())).Returns(Task.CompletedTask).Verifiable();
var syncManager = new SyncManager(_pubClientMock.Object, Mock.Of<ILogger<SyncManager>>());
// Act
await syncManager.Sync();
// Assert
_pubClientMock.Verify(p => p.Push(It.Is<EventModel>(
x => x.Cost.CostName == mockedCost.CostName
&& x.Cost.CostCode == mockedCost.CostCode
&& x.Cost.Active == mockedCost.Active
&& x.MessageType == "CREATE")));
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/491711.html
下一篇:黑客等級串列準備
