测试使用FromServicesAttribute填充的属性

Sha*_*tin 2 c# asp.net-mvc unit-testing moq asp.net-core

我们有一个控制器属性,使用FromServicesAttribute.

[FromServices]
public IGenericRepository<TodoItem> TodoItemRepository { get; }
Run Code Online (Sandbox Code Playgroud)

我们想要使用此属性进行测试.我们如何嘲笑它?例如,如果我们使用构造函数注入,我们可以将模拟实现传递给构造函数.我们如何用这种方式做一个属性?

我们当前的方法

这就是我们目前正在做的事情Moq.

[Fact]
public void GetAll_GetsCollection()
{
    // setup mock repository
    var all = new List<TodoItem>()
    {
        new TodoItem(),
        new TodoItem(),
        new TodoItem()
    };            

    var mockRepo = new Mock<IGenericRepository<TodoItem>>();
    mockRepo.Setup(x => x.All()).Returns(all);

    // setup mock unit of work
    // including what the [FromService] property will return
    var mockUnitOfWork = new Mock<IUnitOfWork>();
    mockUnitOfWork
        .Setup(x =>x.TodoItemRepository)
        .Returns(mockRepo.Object);

    // test controller
    TodoController controller = new TodoController(mockUnitOfWork.Object);
    var result = controller.GetAll();
    Assert.Equal(3, result.Count());
}
Run Code Online (Sandbox Code Playgroud)

这确实有效并通过测试.也许它足够好了.我们是TDD的新手.

Vic*_*aci 5

使属性可设置(如果需要,可以使用内部)并使用该属性InternalsVisibleTo使测试程序集可见setter.然后,在测试代码中构造对象后,设置属性.

或者,如果您在测试代码中使用DI,请创建一个假的IGenericRepository<TodoItem>并让DI容器注入它.

  • `FromServices`修饰属性在ModelBinding阶段分配值,该阶段在动作调用之前.也就是在模型绑定阶段,MVC从DI获取服务并将值赋给属性(正如Victor提到的,您需要为您的属性设置一个setter,否则MVC将无法为该属性赋值).因此,对于这种情况,即使您为单元测试设置DI容器,也不会填充您的属性,因为您只是单元测试控制器并且没有模型绑定阶段.继续... (2认同)