最小起订量单元测试-多重发布方法失败

时间:2018-09-03 10:20:04

标签: c# unit-testing asp.net-core-mvc moq

我已经为ASP.NET CORE MVC应用程序编写了单元测试用例。该函数具有多个发布方法和一个Get方法。第一个Post方法正确注入并测试成功通过,但是第二个Post方法始终为NULL且不注入成功,但是前一个Get&Post操作成功。

此行未正确注入。

_WebService.Setup(test => test.PostRequestAsync<CommonResultDTO>(Constants.SendVerificationCodeAPI, customViewModel)).ReturnsAsync(deserialisedObj);

此调用的返回值始终为空。

var externalApiOutput = await _webService.PostRequestAsync<CommonResultDTO>(Constants.SendVerificationCodeAPI, newModel);  // this value is returning null

MVC控制器

public class AccountController
{

    private readonly IHttpContextAccessor _accessor;   
    public AccountController(IHttpContextAccessor accessor
        , IWebService webService) 

    {
        _accessor = accessor;            
        _webService = webService;
    }

    public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
    {
        if (ModelState.IsValid)
        {
            model.Email = !string.IsNullOrEmpty(model.Email) ? model.Email.ToLowerInvariant() : string.Empty;
            var result = await _webService.PostRequestAsync<CommonResultDTO>(Constants.UserLoginAPI, model);

            if (result.Succeeded)
            {
                var output = JsonConvert.DeserializeObject<UserDto>(result.Object.ToString());

                if (output != null && !string.IsNullOrEmpty(output.Email))
                {
                    var userRoleInfo = await _webService.GetRequestAsync<List<UserRoleViewModel>>(string.Format(Constants.GetUserRoleInfoAPI, output.Email));                       
                    if (userRoleInfo != null)
                    {
                        var claims = new List<Claim>
                        {
                            new Claim(ClaimTypes.Name, output.Email),
                            new Claim("Username", output.UserName),
                            new Claim(ClaimTypes.Role, Convert.ToString(userRoleInfo.FirstOrDefault().Name))
                        };

                        var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);

                        await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), new AuthenticationProperties { IsPersistent = model.RememberMe });

                        if (output.TwoFactorEnabled)
                        {
                            var newModel = sendVerificationCode(output.PhoneNumber, Constants.CountryCodeValue);
                            var externalApiOutput = await _webService.PostRequestAsync<CommonResultDTO>(Constants.SendVerificationCodeAPI, newModel);  // this value is returning null

                            // value of "externalApiOutput " is null, hence the further cases are failing.  
                            if (externalApiOutput != null && externalApiOutput.Succeeded == true)
                            {
                                return RedirectToAction("Login_2FA");
                            }
                        }
                        else
                        {
                            return RedirectToAction("Dashboard", "Home");
                        }
                    }
                }


                return View(new LoginViewModel());
            }
            else
            {                 
                ShowMessage(MessageType.warning.ToString(), Constants.InvalidCredential);
                return View(model);
            }
        }

        // If we got this far, something failed, redisplay form
        return View(model);
    }

    private CustomViewModel sendVerificationCode(string toPhoneNumber, string countryCode)
    {
        var externalModel = new CustomViewModel();

        ExternalAPIService externalService = new ExternalAPIService(_settings);
        externalModel = externalService.GetOtherSettings();

        externalModel.ToPhoneNumber = toPhoneNumber;
        externalModel.CountryCode = countryCode;

        return externalModel;

    }

}

单元测试

public class AccountControllerTest : TestFixture
{
    public AccountControllerTest()
    {

        _accessor = new Mock<IHttpContextAccessor>();
        _WebService = new Mock<IWebService>();


        var authServiceMock = new Mock<IAuthenticationService>();
        authServiceMock
            .Setup(_ => _.SignInAsync(It.IsAny<HttpContext>(), It.IsAny<string>(), It.IsAny<ClaimsPrincipal>(), It.IsAny<AuthenticationProperties>()))
            .Returns(Task.FromResult((object)null));

        var serviceProviderMock = new Mock<IServiceProvider>();
        serviceProviderMock
            .Setup(_ => _.GetService(typeof(IAuthenticationService)))
            .Returns(authServiceMock.Object);

        var urlHelperFactory = new Mock<IUrlHelperFactory>();
        serviceProviderMock
            .Setup(s => s.GetService(typeof(IUrlHelperFactory)))
            .Returns(urlHelperFactory.Object);

        var context = new DefaultHttpContext() {
            RequestServices = serviceProviderMock.Object
        };
        _accessor.Setup(_ => _.HttpContext).Returns(context);


        Mock<ITempDataDictionary> tempData = new Mock<ITempDataDictionary>();

        accountController = new AccountController(_accessor.Object, _WebService.Object)
        {
            ControllerContext = new ControllerContext
            {
                HttpContext = new DefaultHttpContext
                {
                    // How mock RequestServices?
                    RequestServices = serviceProviderMock.Object

                }
            }
            , TempData =tempData.Object
        };

    }

    [Fact]
    public async Task LoginTest_Post_UserHasValidCredentialsAndRoleAndTwoFactor() // this method is failing, hence commented out for time-being
    {
        // Arrange

        var mockModel = new LoginViewModel { };
        mockModel.Email = "test@test.com";
        mockModel.Password = "test123";
        mockModel.RememberMe = false;

        var customViewModel  = new CustomViewModel()
        {           
            ToPhoneNumber = "7009529018",       
            CountryCode = "91"          
        };


        var commonResult = new CommonResultDTO { Object = User(), Succeeded = true, StatusCode = Common.Enums.ResponseStatusCodeEnum.Success };
        var email = User().Email;
        string stringObj = JsonConvert.SerializeObject(commonResult);
        var deserialisedObj = JsonConvert.DeserializeObject<CommonResultDTO>(stringObj);

        var output = GetUserRole();

        _WebService.Setup(test => test.PostRequestAsync<CommonResultDTO>(Constants.UserLoginAPI, mockModel)).ReturnsAsync(deserialisedObj);
        _WebService.Setup(test => test.GetRequestAsync<List<UserRoleViewModel>>(string.Format(Constants.GetUserRoleInfoAPI, email))).ReturnsAsync(output);

        // this method is not injecting correctly and the value is alwasy NULL
        _WebService.Setup(test => test.PostRequestAsync<CommonResultDTO>(Constants.SendVerificationCodeAPI, customViewModel)).ReturnsAsync(deserialisedObj);

        var result = await accountController.Login(mockModel);

        var redirectResult = result as RedirectToActionResult;

        Assert.NotNull(redirectResult);
        Assert.Equal("Home", redirectResult.ControllerName);
        Assert.Equal("Dashboard", redirectResult.ActionName);

    }
}

请建议如何使它工作。

1 个答案:

答案 0 :(得分:1)

当安装程序中使用的参数与进行测试时传递的参数不匹配时,模拟将返回返回类型的默认值。在这种情况下 null

如果参数值无关紧要,则可以使用It.IsAny<T>()来松开匹配项

_WebService
    .Setup(_ => _.PostRequestAsync<CommonResultDTO>(Constants.SendVerificationCodeAPI, It.IsAny<CustomViewModel>()))
    .ReturnsAsync(deserialisedObj);
相关问题