How can I mock my membership provider (I have custom membership provider, but don't know how to mock it and give to membership as provider as Membership.Provider has only getter) and use that mocked custom membership provider in my unit test?
Here is my controller
public class MyController
{
private IMyRepository myRepository;
public MyController(IMyRepository myRepository)
{
this.myRepository= myRepository;
}
[HttpGet]
public ActionResult Create()
{
var user = Membership.GetUser(); // <--- I want mock this method
ViewBag.User = user;
return View("Create");
}
}
And here is my test (using Moq)
[TestClass]
public class MyControllerUnitTest
{
private MyController controller;
public MyControllerUnitTest()
{
Mock<IMyRepository > myRepository = new Mock<IMyRepository>();
var controller = new GroupController(myRepository.Object);
}
[TestMethod]
public void TestMethod1()
{
var result = controller.Create() as ViewResult;
Assert.AreEqual("Create", result.ViewName);
}
}
#Sergey is right, you should not use Membership class directly. I know you will need to user Membership class in some cases hence adding following information.
You need to wrap Membership class in a class (derived from an interface) and then you can mock wherever required.
Cut short version of what we have got:
public interface IMembershipService
{
MembershipUser GetUserDetails(string emailAddress);
void CreateUserRole(string roleName);
void AssignUserToRole(string username, string roleName);
bool ValidateUserCredentials(string username, string password);
void SetAuthenticationCookie(string username, bool rememberMe);
void SignOut();
void UpdateUser(MembershipUser membershipUser);
bool DeleteUser(string username);
}
public class MembershipService : IMembershipService
{
public MembershipUser GetUserDetails(string emailAddress)
{
return Membership.GetUser(emailAddress);
}
public MembershipUser GetUserDetails(Guid membershipId)
{
return Membership.GetUser(membershipId);
}
}
In your controller just get it injected:
public class AdminController : Controller
{
private readonly IMembershipService _membershipService;
private readonly IEmailService _emailService;
public AdminController(IMembershipService membershipService,
IEmailService emailService)
{
_membershipService = membershipService;
_emailService = emailService;
}
}
In unit test you can do:
var membershipService = new Mock<IMembershipService>();
First of all you should inherit MyController from the System.Web.Mvc.Controller class:
public class MyController : System.Web.Mvc.Controller
Then you should avoid using the Membership. It's static and it's not designed to be unit testable. The better choice would be to use the controller's User property:
[HttpGet]
public ActionResult Index()
{
ViewBag.UserName = this.User.Identity.Name;
return View("Index");
}
The controller.User property can be mocked using the ControllerContext:
// arrange
Mock<HttpContextBase> httpContext = new Mock<HttpContextBase>();
httpContext.SetupGet(c => c.User.Identity.Name).Returns("John Doe");
Mock<ControllerBase> baseControler = new Mock<ControllerBase>();
this.controller.ControllerContext =
new ControllerContext(httpContext.Object, new RouteData(), baseControler.Object);
// act
var result = this.controller.Index();
// assert
Assert.AreEqual("John Doe", ((ViewResult)result).ViewBag.UserName);
Related
I use UnitOfWork with repository in an ASP.NET Core 6 Web API and want to use XUnit for testing. I use the code shown below, and it works.
I have two questions:
I use accept-language in the methods to know what is the language for returning correct error messages. How can I add accept-language for test?
How should I use token that I get with Authenticate method?
UnitOfWork
public interface IUnitOfWork : IDisposable
{
IUserRepository UserRepository { get; }
}
public class UnitOfWork : IUnitOfWork
{
protected readonly DatabaseContext db;
private IUserRepository userRepository;
public IUserRepository UserRepository
{
get
{
if (userRepository == null)
{
userRepository = new UserRepository(db);
}
return userRepository;
}
}
//...
}
UserRepository
public interface IUserRepository : IGenericRepository<UserRole>
{
Task<User> GetUserWithRolesAsync(string username);
}
public class UserRepository : GenericRepository<User>, IUserRepository
{
public async Task<User> GetUserWithRolesAsync(string username)
{
//...
}
}
AuthController
private readonly IUnitOfWork _uow;
public AuthController(IUnitOfWork uow) : base(uow)
{
_uow = uow;
}
[HttpPost("authenticate")]
public async Task<IActionResult> Authenticate([FromBody] UserLoginViewModel Request)
{
User user = await _uow.UserRepository.GetUserWithRolesAsync(Request.Username);
//....
}
Test method:
[Fact]
public async Task Authenticate_WithInvalidUsernamePassword_ReturnsNotFound()
{
// Arrange
var dbOption = new DbContextOptionsBuilder<DatabaseContext>().UseSqlServer("connection string").Options;
DatabaseContext databaseContext = new DatabaseContext(dbOption);
databaseContext.Database.EnsureCreated();
var jwtAuthenticatorManager = new JwtAuthenticatorManager("key");
var unitOfWorkStub = new Mock<IUnitOfWork>();
UserRepository userRep = new UserRepository(databaseContext);
unitOfWorkStub.SetupGet(uow => uow.UserRepository).Returns(userRep);
var options = Options.Create(new LocalizationOptions { ResourcesPath = "Resources" });
var factory = new ResourceManagerStringLocalizerFactory(options, NullLoggerFactory.Instance);
var localizer = new StringLocalizer<SharedTranslate>(factory);
var controller = new AuthController(unitOfWorkStub.Object, localizer, jwtAuthenticatorManager);
UserLoginViewModel userLoginViewModel = new UserLoginViewModel
{
Username = "admin",
Password = "admin#123"
};
// Act
var result = await controller.Authenticate(userLoginViewModel);
// Assert
result.Should().BeOfType<NotFoundResult>();
}
I have dot net core website , based on dependency injection ,the controller is.
public class TokenController : Controller
{
private IConfiguration _config;
private readonly IUserService _iuserService;
public TokenController(IConfiguration config, IUserService iUserService)
{
_config = config;
_iuserService = iUserService;
}
public UserViewModel Authenticate(LoginModel login)
{
UserViewModel user = null;
user = this._iuserService.Login(login.Username, login.Password);
return user;
}
}
and i want to do unit test for Authenticate method ,the unit test class is ,
[TestClass]
public class TokenUnitTest
{
private IUserService _IUserService;
private IConfiguration _config;
[TestInitialize]
public void Setup()
{
var mockIUserService = new Mock<IUserService>();
UserViewModel returnedobj = new UserViewModel();
returnedobj.Email = "sam#sam.com";
returnedobj.Name = "sam";
mockIUserService.Setup(x => x.Login("sam", "123")).Returns(returnedobj);
_IUserService = mockIUserService.Object;
var _configurationRoot = new Mock<IConfigurationRoot>();
_configurationRoot.SetupGet(x => x[It.IsAny<string>()]).Returns("Key");
this._config = _configurationRoot.Object;
}
[TestMethod]
public void Authenticate()
{
////arrange
LoginModel _LoginModel = new LoginModel("sam", "123");
var config = InitConfiguration();
var clientId = config["CLIENT_ID"];
TokenController _TokenController = new TokenController(config, _IUserService);
////act
UserViewModel LoginnedUser = _TokenController.Authenticate(_LoginModel);
////assert
Assert.IsNotNull(LoginnedUser);
}
}
The problem is when i put break point at authenticate method it return the returnd data that exist in setupMock. Why it doesn't go to database and return the true data.
the second problem is the breakpoint doesn't enter in UserService ,it deal with interface ,, why dependency injection doesn't work ??
For an integration test no mocking is required:
[TestInitialize]
public void Setup()
{
_IUserService = new UserService(); // create a real instance
}
I'm trying to test my project. I have never used tests before and I am starting to learn I would like a help, in the simplest case I want test this public ActionResult Index() but I don't know how to Inject those dependencies.
Controller:
Controller:
public class WorkPlacesController : Controller
{
private readonly IWorkPlaceService workPlaceService;
public WorkPlacesController(IWorkPlaceService workPlaceService)
{
this.workPlaceService = workPlaceService;
}
// GET: WorkPlaces
public ActionResult Index()
{
var workPlaces = workPlaceService.GetWorkPlaces(includedRelated:
true);
return View(workPlaces);
}
}
Here is my Service
Service
public class WorkPlaceService : IWorkPlaceService
{
private readonly IWorkPlaceRepository workPlacesRepository;
private readonly IUnitOfWork unitOfWork;
public WorkPlaceService(IWorkPlaceRepository workPlacesRepository, IUnitOfWork unitOfWork)
{
this.workPlacesRepository = workPlacesRepository;
this.unitOfWork = unitOfWork;
}
}
public interface IWorkPlaceService
{
IEnumerable<WorkPlace> GetWorkPlaces(string workPlaceDescription = null, bool includedRelated = true);
}
And my Repository
Repository
public class WorkPlaceRepository : RepositoryBase<WorkPlace>, IWorkPlaceRepository
{
public WorkPlaceRepository(IDbFactory dbFactory)
: base(dbFactory) { }
public WorkPlace GetWorkPlaceByDescription(string workPlaceDescription)
{
var workPlace = this.DbContext.WorkPlaces.Where(c => c.Description == workPlaceDescription).FirstOrDefault();
return workPlace;
}
}
public interface IWorkPlaceRepository : IRepository<WorkPlace>
{
WorkPlace GetWorkPlaceByDescription(string workPlaceDescription);
}
Factory
public class DbFactory : Disposable, IDbFactory
{
AgendaEntities dbContext;
public AgendaEntities Init()
{
return dbContext ?? (dbContext = new AgendaEntities());
}
protected override void DisposeCore()
{
if (dbContext != null)
dbContext.Dispose();
}
}
I tried to do something like this:
public void BasicIndexTest()
{
// Arrange
var mockRepository = new Mock<IWorkPlaceService>();
var controller = new WorkPlacesController(mockRepository.Object);
// Act
ActionResult actionResult = controller.Index() as ViewResult;
// Assert
Assert.IsInstanceOfType(actionResult, typeof(List<WorkPlace>));
}
How do I inject in this controller the data needed to go in the database and bring the results?
I Want test this public ActionResult Index() but I don't know how to Inject those dependencies.
Mock the behavior of required dependencies of the controller for the test and assert the desired behavior when the test is exercised.
For example, based on what you have done so far
public void BasicIndexTest() {
// Arrange
var mockService = new Mock<IWorkPlaceService>();
var workPlaces = new List<WorkPlace>() {
new WorkPlace()
};
mockService
.Setup(_ => _.GetWorkPlaces(It.IsAny<string>(), It.IsAny<bool>()))
.Returns(workPlaces);
var controller = new WorkPlacesController(mockService.Object);
// Act
var actionResult = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(actionResult);
var model = actionResult.Model;
Assert.IsNotNull(model)
Assert.IsInstanceOfType(model, typeof(List<WorkPlace>));
Assert.AreEqual(workPlaces, model);
}
Only the IWorkPlaceService was needed for the testing of Index action, but fake data was needed for the invocation of the GetWorkPlaces method. So the mock was configured to return a list of objects when called and pass it to the view result.
I am working on a Asp.net MVC 5 project and I am trying to setup a mock to return a custom principal within a controller. I have search and tried different approach suggested but none of them works.
I have a BaseController which all my controllers inherit from. The BaseController has a User property which return HttpContext.User in the getter. The HttpContext.user returns a value when called within the project but return a null when call from a unit test project.
BaseController
public class BaseController : Controller
{
protected virtual new CustomPrincipal User
{
get { return HttpContext.User as CustomPrincipal; } ***<== Line with issue***
}
}
Custom Principal
public class CustomPrincipal : IPrincipal, ICustomPrincipal
{
public IIdentity Identity { get; private set; }
public string UserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsStoreUser { get; set; }
public CustomPrincipal(string username)
{
this.Identity = new GenericIdentity(username);
}
}
Controller
public class DocumentsController : BaseController
{
public ViewResult ViewDocuments()
{
var userType = User.IsStoreUser ? UserType.StoreUser : UserType.Corporate; ***<== User is null when calling from a unit test.***
}
}
Test Case
[Test]
public void ViewDocuments_WhenCalled_ShouldReturnViewModel()
{
// Arrange
var principal = new CustomPrincipal("2038786");
principal.UserId = "2038786";
principal.FirstName = "Test";
principal.LastName = "User";
principal.IsStoreUser = true;
var _mockController = new Mock<DocumentsController>(new UnitOfWork(_context)) { CallBase = true };
_mockController.Setup(u => u.User).Returns(principal); ***<== Error - "Invalid setup on a non-virtual (overridable in VB) member: u => u.User"***
// Act
var result = _controller.ViewDocuments();
}
I'm using nUnit and Moq to create the mock object but I not sure what I'm doing wrong. I need to mock the return of User.IsStore in the DocumentControl to return the value of IsStore in the custom principal object i created in the test.
Make a mock http context
private class MockHttpContext : HttpContextBase {
private readonly IPrincipal user;
public MockHttpContext(IPrincipal principal) {
this.user = principal;
}
public override IPrincipal User {
get {
return user;
}
set {
base.User = value;
}
}
}
Arrange test accordingly.
[Test]
public void ViewDocuments_WhenCalled_ShouldReturnViewModel() {
// Arrange
var principal = new CustomPrincipal("2038786");
principal.UserId = "2038786";
principal.FirstName = "Test";
principal.LastName = "User";
principal.IsStoreUser = true;
var mockUoW = new Mock<IUnitOfWork>();
//...setup UoW dependency if needed
var controller = new DocumentsController(mockUoW.Object);
controller.ControllerContext = new ControllerContext {
Controller = controller,
HttpContext = new MockHttpContext(principal)
};
// Act
var result = controller.ViewDocuments();
//Assert
//...assertions
}
Don't mock system under test. Mock its dependencies.
It gets a lot easier if you don't depend on HttpContext directly. Create an IUserProvider interface and an implementation that depends on HttpContext (e.g. HttpContextUserProvider), then stub the IUserProvider in your tests.
The IUserProvider should be passed along to your controller via dependency injection.
I want to know how to unit test my controller when it inherits from a base controller that is dependent on HttpContext. Below is my inherited controller called BaseInterimController. And below that is the AccountController method that I wish to Unit Test. We are using MOQ.
public abstract class BaseInterimController : Controller
{
#region Properties
protected string InterimName
{
get { return MultiInterim.GetInterimName(InterimIdentifier); }
}
internal virtual string InterimIdentifier
{
get { return System.Web.HttpContext.Current.Request.RequestContext.RouteData.Values["InterimIdentifier"].ToString(); }
}
}
public class AccountController : BaseInterimController
{
[HttpPost]
[AllowAnonymous]
[ValidateInput(false)]
[Route(#"{InterimIdentifier:regex([a-z]{7}\d{4})}/Account/Signin")]
public ActionResult Signin(LoginViewModel model)
{
if (ModelState.IsValid)
{
var identity = Authentication.SignIn(model.Username,
model.Password) as LegIdentity;
if (identity != null && identity.IsAuthenticated)
{
return Redirect(model.ReturnUrl);
}
else
{
// Sign in failed
ModelState.AddModelError("",
Authentication.ExternalSignInFailedMessage);
}
}
return View(model);
}
}
Coupling your controller to HttpContext can make your code very difficult to test because during unit tests HttpContext is null unless you try to mock it; which you shouldn't really do. Don't mock code you don't own.
Instead try abstracting the functionality you want to get from HttpContext into something you have control over.
this is just an example. You can try to make it even more generic if needed. I will focus on your specific scenario.
You are calling this directly in your controller
System.Web.HttpContext.Current.Request
.RequestContext.RouteData.Values["InterimIdentifier"].ToString();
When what you are really after is the ability to get that InterimIdentifier value. Something like
public interface IInterimIdentityProvider {
string InterimIdentifier { get; }
}
public class ConcreteInterimIdentityProvider : IInterimIdentityProvider {
public virtual string InterimIdentifier {
get { return System.Web.HttpContext.Current.Request.RequestContext.RouteData.Values["InterimIdentifier"].ToString(); }
}
}
which can later be implemented in a concrete class and injected into your controller provided you are using Dependency Injection.
Your base controller will then look like
public abstract class BaseInterimController : Controller {
protected IInterimIdentityProvider identifier;
public BaseInterimController(IInterimIdentityProvider identifier) {
this.identifier = identifier;
}
protected string InterimName {
get { return MultiInterim.GetInterimName(identifier.InterimIdentifier); }
}
//This can be refactored to the code above or use what you had before
//internal virtual string InterimIdentifier {
// get { return identifier.InterimIdentifier; }
//}
}
public class AccountController : BaseInterimController
{
public AccountController(IInterimIdentityProvider identifier)
: base(identifier){ }
[HttpPost]
[AllowAnonymous]
[ValidateInput(false)]
[Route(#"{InterimIdentifier:regex([a-z]{7}\d{4})}/Account/Signin")]
public ActionResult Signin(LoginViewModel model)
{
if (ModelState.IsValid)
{
var identity = Authentication.SignIn(model.Username,
model.Password) as LegIdentity;
if (identity != null && identity.IsAuthenticated)
{
return Redirect(model.ReturnUrl);
}
else
{
// Sign in failed
ModelState.AddModelError("",
Authentication.ExternalSignInFailedMessage);
}
}
return View(model);
}
}
This allows implemented controllers to not be dependent on HttpContext which will allow for better unit testing as you can easily mock/fake IInterimIdentityProvider interface using Moq to return what you want during tests.
[TestMethod]
public void Account_Controller_Should_Signin() {
//Arrange
var mock = new Mock<IInterimIdentityProvider>();
mock.Setup(m => m.InterimIdentifier).Returns("My identifier string");
var controller = new AccountController(mock.Object);
var model = new LoginViewModel() {
Username = "TestUser",
Password = ""TestPassword
};
//Act
var actionResult = controller.Signin(model);
//Assert
//...assert your expected results
}