我应该如何对返回模型的控制器进行单元测试?

本文关键字:控制器 单元测试 模型 返回 我应该 | 更新日期: 2023-09-27 18:16:05

我有一个名为PostsController的控制器

public class PostsController : Controller
{
    private readonly IPostsRepository repository;
    public PostsController(IPostsRepository repository)
    {
        this.repository = repository;
    }
    public ViewResult Index()
    {
        var posts =
            repository.All()
                      .OrderBy(post => post.PublishedAt);
        return View("Index", posts.MapTo<PostViewModel>());
    }
}

和相应的测试夹具PostsControllerTest

[TestFixture]
public class PostsControllerTest
{
    private PostsController controller;
    private Mock<IPostsRepository> repository;
    [SetUp]
    public void SetUp()
    {
        AutoMapperConfig.Configure();
        repository = new Mock<IPostsRepository>();
        controller = new PostsController(repository.Object);
    }
    [Test]
    public void Index_ReturnsCorrectModel()
    {
        var actual = controller.Index().Model;
        Assert.IsAssignableFrom<IEnumerable<PostViewModel>>(actual);
    }
}

目前我只测试控制器是否返回正确的模型类型。是否还应该存根存储库并测试返回的数据是否正确,如下所示:

[Test]
public void Index_ReturnsCorrectModel()
{
    var post = new Post
    {
        Slug = "continuing-to-an-outer-loop",
        Title = "Continuing to an outer loop",
        Summary = "When you have a nested loop, sometimes",
        Content = "When you have a nested loop, sometimes",
        PublishedAt = DateTime.Now.AddDays(7),
        Tags = new Collection<Tag> { new Tag { Name = "Programming" } }
    };
    repository.Setup(repo => repo.All()).Returns(new[] { post });
    var actual = controller.Index().Model as IEnumerable<PostViewModel>;
    Assert.NotNull(actual);
    Assert.AreEqual(1, actual.Count());
    Assert.AreEqual(post.Title, actual.First().Title);
}

我感到很沮丧,不知道我是否正确的单元测试。如果能清楚地说明我应该采取什么措施,那将非常有帮助。

我应该如何对返回模型的控制器进行单元测试?

我认为你不需要在这个单元测试中测试IPostRepository的功能。您应该为它创建一个单独的单元测试类。

同样,应该单独测试MapTo<T>的功能。

单元测试应该只测试SUT(被测系统)的功能,在这种情况下是PostsController类的Index方法。

这是一个简单的方法,所以你想在这个单元测试中验证的两件事是:

1- repository.All()方法被调用一次

2-你的视图模型被正确映射(你已经在做)

我将这样对这个方法进行单元测试:

[Test]
    public void Index_ReturnsCorrectModel()
    {
        // Arrange
        repository.Setup(repo => repo.All()).Returns(Enumerable.Empty<Post>());
        // Act
        var actual = controller.Index().Model;
        // Assert
        Assert.IsAssignableFrom<IEnumerable<PostViewModel>>(actual);
        repository.Verify(repo => repo.All(), Times.Once);
    }

同样,为了尽量减少安排单元测试所需的工作量,可以使用像AutoFixture这样的库,它将自动为您创建post对象。