首页 > 解决方案 > ViewComponent 的 XUnit 测试返回空结果?

问题描述

我正在尝试使用 XUnit 测试我的 ViewComponent。当我调试组件并在它返回组件视图之前设置一个断点时,模型就设置好了。

这是我要返回的简单模型。

public class IntDashMakeRecAssgnmntsPoRespMngrVM
{
    public IEnumerable<Audit> Audits { get; set; }
}

我试图断言 Audits.Count() 大于 0。

这是我的视图组件:

public class IntDashMakeRecAssgnmntsPoRespMngrViewComponent : ViewComponent
{
    private IAuditRepository _auditRepo;
    private IExternalRepository _externalRepo;
    public IntDashMakeRecAssgnmntsPoRespMngrViewComponent(IAuditRepository auditRepo,
        IExternalRepository externalRepo)
    {
        _auditRepo = auditRepo;
        _externalRepo = externalRepo;
    }

    public IViewComponentResult Invoke()
    {
        ClaimsPrincipal user = HttpContext.Request.HttpContext.User;
        short staffId = short.Parse(user.Claims.Single(c => c.Type == "StaffId").Value);

        // Get all Internal Audits that are not closed and not completed
        var audits = _auditRepo.Audits
            .Include(a => a.Findings).ThenInclude(f => f.Recommendations).ThenInclude(r => r.Assignments)
            .Where(a => a.StatusID != 3 && a.StatusID != 11);
        var external = _externalRepo.ExternalRecords;
        audits = audits.Where(a => !external.Any(e => e.AuditID == a.AuditID));

        if (User.IsInRole("PAG_SPEC") && !User.IsInRole("PAG_ADMIN_INT"))
        {
            audits = audits.Where(a =>
                a.Assignments.Any(assn => assn.AssignmentAuditId == a.AuditID
                && assn.AssignmentRoleId == 2 && assn.AssignmentStaffId == staffId));
        }

        // Where audit has a recommendation without an assigned PO Authorizer
        //    OR without an assigned Responsible Manager (Rec Level).
        List<Audit> auditsToAssign = new List<Audit>();
        foreach (Audit audit in audits)
        {
            foreach (Finding finding in audit.Findings)
            {
                foreach (Recommendation rec in finding.Recommendations)
                {
                    if (!rec.Assignments.Any(asgn => asgn.AssignmentRoleId == 15)
                            || !rec.Assignments.Any(asgn => asgn.AssignmentRoleId == 26)
                        )
                    {
                        auditsToAssign.Add(rec.Finding.Audit);
                        break;
                    }
                }
            }
        }

        IntDashMakeRecAssgnmntsPoRespMngrVM intDashMakeRecAssgnmntsPoRespMngrVM =
            new IntDashMakeRecAssgnmntsPoRespMngrVM
            {
                Audits = auditsToAssign
            };

        return View("/Views/InternalAudit/Components/Dashboard/IntDashMakeRecAssgnmntsPoRespMngr/Default.cshtml", intDashMakeRecAssgnmntsPoRespMngrVM);
    }
}

当我在调试和中断检查时到达这一行时,我有 1 个我想要的审核:

return View("/Views/InternalAudit/Components/Dashboard/IntDashMakeRecAssgnmntsPoRespMngr/Default.cshtml", intDashMakeRecAssgnmntsPoRespMngrVM);

在此处输入图像描述

现在这是我的单元测试:

    [Fact]
    public void ReturnsAudit_1Finding_1Rec_1Asgn_PONeeded_RespMnrAssigned()
    {
        // Arrange
        var audits = new Audit[]
        {
            new Audit { AuditID = 1 }
        };

        var findings = new Finding[]
        {
            new Finding{ Audit = audits[0], FindingId = 1 }    // 1 Finding
        };

        var recommendations = new List<Recommendation>()
        {
            new Recommendation  // 1 Rec
            {
                Finding = findings[0],
                Assignments = new List<Assignment>()
                {
                    // PO Authorizor
                    new Assignment { AssignmentRoleId = 15 }
                    // No Responsible Manager
                }
            }
        };

        audits[0].Findings = findings;
        findings[0].Recommendations = recommendations;

        Mock<IAuditRepository> mockAuditRepo = new Mock<IAuditRepository>();
        mockAuditRepo.Setup(m => m.Audits).Returns(audits.AsQueryable());
        Mock<IExternalRepository> mockExternalRepo = new Mock<IExternalRepository>();
        mockExternalRepo.Setup(m => m.ExternalRecords).Returns(
            new External[0].AsQueryable() 
        );

        // Act
        var component = new IntDashMakeRecAssgnmntsPoRespMngrViewComponent(
            mockAuditRepo.Object, mockExternalRepo.Object);
        component.ViewComponentContext = new ViewComponentContext();
        component.ViewComponentContext.ViewContext.HttpContext = TestContext;

        var result =
            component.Invoke() as IntDashMakeRecAssgnmntsPoRespMngrVM;
        int auditCount = (result).Audits.Count();

        // Assert
        Assert.Equal(1, auditCount);
    }

为什么这一行的结果为空?

var result = 
            component.Invoke() as IntDashMakeRecAssgnmntsPoRespMngrVM;

我也先尝试了这个,它仍然是空的:

ViewComponentResult result =
            component.Invoke() as ViewComponentResult;
        int auditCount =
            ((IntDashMakeRecAssgnmntsPoRespMngrVM)result.Model).Audits.Count();

标签: asp.net-core-mvcxunit.netasp.net-core-viewcomponent

解决方案


我想到了。我没有将结果转换为正确的类型。

我有这个:

ViewComponentResult result =
        component.Invoke() as ViewComponentResult;
    int auditCount =
        ((IntDashMakeRecAssgnmntsPoRespMngrVM)result.Model).Audits.Count();

应该是这样的:

var result =
            component.Invoke() as ViewViewComponentResult;
        int auditCount =
            ((IntDashMakeRecAssgnmntsPoRespMngrVM)result.ViewData.Model).Audits.Count();

ViewViewComponentResult 而不是 ViewComponentResult。


推荐阅读