欧克:参数null参考中的对象验证对象

发布于 2025-02-06 09:29:10 字数 4655 浏览 1 评论 0原文

我正在尝试浏览同步过程,但是我遇到了一个特定部分的问题。

在我的方法中,我试图订阅以下操作:

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 eventmodel object < /代码>正在使用正确的值创建。

但是,在我调用_pubClientMock.verify();时,我在测试中获得了system.nullReferenceException: 似乎X.COST在这里无效。

知道为什么这个属性是无效的还是我在这里做错了什么?

因此,要再次迭代,实际调用.sync()并使用调试器逐步逐步逐步启动。 _pubClientMock.verifynullReferenceException上失败。

I'm trying to Moq a synchronization process, but I'm having issues with one specific part.

In my method I'm trying to Moq I perform the following:

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;
    }
}

My tests I have set up to like this:

    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")));
        }
    }

When I run this test, every piece of code is called correctly and while debugging I see that the EventModel object is being created with the correct values.

However in my test when I call _pubClientMock.Verify(); I get a System.NullReferenceException:
It seems like the x.Cost is NULL here.

Any idea why this property would be NULL or what I'm doing wrong here?

So to iterate again, actually calling the .Sync() and stepping through the code with the debugger works perfectly. It's the _pubClientMock.Verify that fails with with a NullReferenceException.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

锦欢 2025-02-13 09:29:10

类似于已经提供的答案之一,我建议您放松设置,以避免使用it.isany避免引用相等的问题。这将使测试案例可以完成。

至于验证中的null参考错误,因为更新的示例将具有一个事件模型将具有null COPT属性值的情况,因此在验证谓词时,您需要检查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")));
    }
}

Similar to the one of the already provided answers I would suggest relaxing the setup to avoid issues with referential equality by using It.IsAny. This will allow the test case to flow to completion.

As for the null reference error in the Verification, because the updated example will have a situation where one of the event models will have a null Cost property value, you will need to check for null when verifying the predicate

[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")));
    }
}
池予 2025-02-13 09:29:10

您能否提供有关通过GetAndSendCost()()的日志的更多详细信息,也许来自该部分,您可以使用它。

// 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")));

Can you provide more detail about Log you pass through GetAndSendCost() maybe the problem comes from that part, you can use 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")));
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文