为了账号安全,请及时绑定邮箱和手机立即绑定

测试 .NET Core 控制器视图组件

测试 .NET Core 控制器视图组件

C#
MMMHUHU 2021-08-29 17:57:13
在.NET的核心,我们有在呼唤具有依赖注入ViewComponent,按照微软的文档模式的控制器操作在这里。如果我们有一个控制器动作返回这样的渲染视图:public class MyController : Controller{    private readonly IToDoContext _todoContext;    public MyController(IToDoContext todoContext)    {        _todoContext = todoContext;    }    public IActionResult IndexVC()    {        return ViewComponent("PriorityList", new { maxPriority = 3, isDone = false });    }}还有一个具有如下依赖注入的 ViewComponent:public class PriorityListViewComponent : ViewComponent{    private readonly ToDoContext db;    public PriorityListViewComponent(ToDoContext context)    {        db = context;    }    public async Task<IViewComponentResult> InvokeAsync(int maxPriority, bool isDone)    {        var items = await GetItemsAsync(maxPriority, isDone);        return View(items);    }    private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)    {        return db.ToDo.Where(x => x.IsDone == isDone && x.Priority <= maxPriority).ToListAsync();    }}我们如何在控制器动作单元测试中将 ToDoContext 注入到 ViewComponent 中?到目前为止, result.Model 始终为空,因为似乎没有办法将 ToDoContext db 注入控制器,然后再注入 ViewComponent。[Fact]public void Should_return_viewcomponent(){    var mockToDoContext = new Mock<IToDoContext>();    mockToDoContext.Setup(m => m.Get()).ReturnsAsync(new ToDoContext());    var sut = new MyController(mockToDoContext.Object);    var result = sut.PriorityListViewComponent("myparams") as ViewComponentResult;    // ToDoContext db is never set, so the result.Model is always null}
查看完整描述

1 回答

?
隔江千里

TA贡献1906条经验 获得超10个赞

仅供参考:我认为微软的例子是错误的。一旦我将 View Component 更改为 View 并将数据从 View Component 代码中获取到后面并移到 Controller 中,那么一切都变得容易测试和实现 Bad Request 逻辑,等等。只需记住将 View Component 移出 View Component 目录,并在视图中将 layout 设置为 null。


控制器应该看起来更像这样:


public class MyController : Controller

{

    private readonly IToDoContext _db;

    public MyController(IToDoContext db)

    {

        _db = db;

    }


    public async Task<IActionResult> IndexVC("PriorityList", new { maxPriority, isDone = false })

        {

            if (string.IsNullOrWhiteSpace(maxPriority))

                return BadRequest($"maxPriority cannot be empty");


            var model = await InvokeAsync(maxPriority, isDone);


            if (model == null)

            {

                return BadRequest($"model not found");

            }


            return View(model);

        }


    public async Task<IViewComponentResult> InvokeAsync(

        int maxPriority, bool isDone)

        {

            var items = await GetItemsAsync(maxPriority, isDone);

            return View(items);

        }

        private Task<List<TodoItem>> GetItemsAsync(int maxPriority, bool isDone)

        {

            return _db.ToDo.Where(x => x.IsDone == isDone &&

                                 x.Priority <= maxPriority).ToListAsync();

        }

}

单元测试看起来像:


[Fact]

public void Should_return_viewcomponent()

{

    var mockToDoContext = new Mock<IToDoContext>();

    mockToDoContext.Setup(m => m.Get())

        .ReturnsAsync(new ToDoContext());


    var sut = new MyController(mockToDoContext.Object);


    var result = await sut.PriorityList("myparams") as ViewResult;

    result.Model.ShouldNotBeNull();

    var resultModel = result.Model as PriorityListModel;

    resultModel.ShouldNotBeNull();

    resultModel.Thing.ShouldBe("whatever");

}

Bad Request 单元测试看起来像这样(注意 BadRequestObjectResult):


[Fact]

public async Task Should_return_bad_request_if_result_not_found()

{

    var mockToDoContext = new Mock<IToDoContext>();

    mockToDoContext.Setup(m => m.Get())

        .ReturnsAsync(null);


    var httpContext = new DefaultHttpContext();


    var sut = new MyController(mockToDoContext.Object)

    {

        ControllerContext = new ControllerContext { HttpContext = httpContext }

    };

    var result = await sut.PriorityList("myparams") as BadRequestObjectResult;


    result.ShouldNotBeNull();

    result.StatusCode.ShouldBe(400);

    result.Value.ShouldBe("model not found");

}


查看完整回答
反对 回复 2021-08-29
  • 1 回答
  • 0 关注
  • 182 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信