带依赖注入的单元测试控制器

时间:2018-02-22 01:31:40

标签: asp.net-mvc unit-testing dependency-injection

我已经厌倦了填写字段然后登录注销以进行简单的测试。

我搜索xUnit和NUnit,但我找到了几个tuturials但是。我想测试我对AccountController的修改(asp.net core 2 mvc)我用一个存储库把这个repo放到逻辑上。

问题是如何使用所有这些依赖注入来安排测试。

控制器示例。

namespace Inside.Controllers
{
[Authorize]
[Route("[controller]/[action]")]
public class AccountController : Controller
{
    private readonly UserManager<ApplicationUser> _userManager;
    private readonly SignInManager<ApplicationUser> _signInManager;
    private readonly IEmailSender _emailSender;
    private readonly ILogger _logger;
    private readonly IUsersRepository _users;

    public AccountController(
            UserManager<ApplicationUser> userManager,
            SignInManager<ApplicationUser> signInManager,
            IEmailSender emailSender,
            ILogger<AccountController> logger,
            IUsersRepository users
        )
    {
        _userManager = userManager;
        _signInManager = signInManager;
        _emailSender = emailSender;
        _logger = logger;
        _users = users;
    }

    [HttpGet]
    [AllowAnonymous]
    public IActionResult RegisterFirstUser(string returnUrl = null)
    {
        if (!_users.HasUsersInDB())
        {
            return RedirectToAction(nameof(SetupWebApp));
        }
        if (!_users.HasOnlySystemUser())
        {
            return RedirectToAction(nameof(Login)); ;
        }
        ViewData["ReturnUrl"] = returnUrl;
        return View();
    }
}

现在我不知道如何测试这个控制器,因为有很多依赖注入。特别是这两个UserManager userManager,SignInManager signInManager

抱歉新手问题。 :P

1 个答案:

答案 0 :(得分:2)

您可以使用Moq轻松完成此操作。假设你的控制器有这个签名:

public class UsersController : Controller
{
    private IUserRepository _userRepository;
    private ApplicationUserManager _userManager;
    private ApplicationSignInManager _signInManager;

    public UsersController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, IUserRepository userRepository)
    {
        UserManager = userManager;
        SignInManager = signInManager;
        _userRepository = userRepository;
    }

 ...
} 

然后对此的测试看起来像这样(使用Moq)

 [TestClass]
public class UsersControllerTests
{
    private Mock<IUserRepository> _userRepository;
    private Mock<ApplicationUserManager> _userManager;
    private Mock<ApplicationSignInManager> _signInManager;
    private UsersController _controller;
    private Mock<IUserStore<ApplicationUser>> _userStore;
    private Mock<IAuthenticationManager> _authManager;

    [TestInitialize]
    public void SetUp()
    {
        _userRepository = new Mock<IUserRepository>();

        _userStore = new Mock<IUserStore<ApplicationUser>>();
        _authManager = new Mock<IAuthenticationManager>();
        _userManager = new Mock<ApplicationUserManager>(_userStore.Object);
        _signInManager = new Mock<ApplicationSignInManager>(_userManager.Object, _authManager.Object);

        _controller = new UsersController(_userManager.Object, _signInManager.Object, _userRepository.Object);

        //only do this if you want to use request object in your tests
        var returnUrl = new Uri("http://www.example.com");
        var httpContext = new Mock<HttpContextBase>();
        var request = new Mock<HttpRequestBase>();
        httpContext.Setup(x => x.Request).Returns(request.Object);
        request.Setup(x => x.Url).Returns(new Uri("http://localhost:123"));
        var requestContext = new RequestContext(httpContext.Object, new RouteData());
        _controller.Url = new UrlHelper(requestContext);
    }