首页 > 解决方案 > 与 asp.net 核心的集成测试(没有视图的控制器测试)

问题描述

我正在尝试设置一个测试项目来测试具有身份和数据库的控制器,而无需定义视图。

我有一个单元测试项目,我可以通过实例化它来测试我的控制器,将 dbContext 传递给构造函数。

 public class EventControllerTests
    {
        private readonly IEventRepository _eventRepository;
        private readonly EventController _controller;
        private readonly AppDbContext dbContext;

        const string cn = "Data Source=(localdb)\\MSSQLLocalDB;Initial Catalog=EventDb;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False";

        public EventControllerTests()
        {

            var options = new DbContextOptionsBuilder<EVNTS.Web.Database.AppDbContext>()
                .UseSqlServer(cn).Options;
            dbContext = new EVNTS.Web.Database.AppDbContext(options);
            // Arrange
            _eventRepository = new EventRepository(dbContext);
            _controller = new EVNTS.Web.Controllers.EventController(_eventRepository);
        }

        [Fact]
        public void ActionIndexTest()
        {
            // Act
            var result = _controller.Index(1);

            // Assert
            var model = (Event)result.Model;
            Assert.Equal(1, model.Id);
        }
    }

我有一个使用 WebApplicationFactory 的集成测试项目

 public class BasicTests : IClassFixture<WebApplicationFactory<EVNTS.Startup>>
    {
        private readonly WebApplicationFactory<EVNTS.Startup> _factory;
        private readonly HttpClient _client;

        public BasicTests(WebApplicationFactory<EVNTS.Startup> factory)
        {
            _factory = factory;
            _client = _factory.CreateClient();
        }

        [Theory]
        [InlineData("/")]
        public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url)
        {

            // Act
            var response = await _client.GetAsync(url);

            // Assert
            response.EnsureSuccessStatusCode(); // Status Code 200-299
            Assert.Equal("text/html; charset=utf-8",
                response.Content.Headers.ContentType.ToString());
        }


        [Fact]

        public async Task TestUserRegistration()
        {
            var s = _factory.Services.GetRequiredService<EVNTS.Web.Repositories.IEventRepository>();
            var url = "/user/register";
            var inputModel = new EVNTS.Web.ViewModels.RegisterModel()
            {
                UserName = "eric",
                Password = "123456",
                ConfirmPassword = "123456"
            };
            var sObj = JsonSerializer.Serialize(inputModel);
            var content = new StringContent(sObj, Encoding.UTF8, "application/json");
            content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
            var response = await _client.PostAsync(url, content);
            var result = response.Content.ReadAsStringAsync();
        }

    }

问题是,使用第二个选项,必须创建视图,我需要使用 AngleSharp 之类的库来测试结果。

我想要介于两者之间的东西,我可以直接调用构造函数并测试结果视图,但 DI 会为我注入 UserManager 和 dbContext。

有任何想法吗?

干杯

这是控制器:

public class UserController : Controller
    {
        private readonly UserManager<User> _userManager;
        public UserController(UserManager<User> userManager)
        {
            _userManager = userManager;
        }

        [HttpPost]
        public async Task<IActionResult> Register([FromBody] RegisterModel model)
        {
            IdentityResult? result=null;

            if (ModelState.IsValid)
            {
                var user = await _userManager.FindByNameAsync(model.UserName);
                if (user == null)
                {
                    user = new User
                    {
                        Id = Guid.NewGuid(),
                        UserName = model.UserName,
                    };
                    result = await _userManager.CreateAsync(user, model.Password);
                }
            }
            return View(result);
        }
    }

标签: c#asp.net-coretestingxunit

解决方案


当您想在集成测试条件下检查控制器的结果而不检查视图时,我也发现这有时很有用。

您可以使用依赖注入并从WebApplicationFactory.

        using (var serviceScope = Factory.Services.CreateScope())
        {
            var sut= serviceScope.ServiceProvider.GetService<YourController>();

        }

要完成这项工作,您必须调用方法AddControllersAsServices()Startup.csDI 容器中注册控制器

            services.AddControllersWithViews(options => { options.ConfigureMvcOptionsForPortalModule(); })
            .SetCompatibilityVersion(CompatibilityVersion.Version_3_0)
            .AddControllersAsServices();//add controller in DI to access it in integration testing

推荐阅读