Mocking method used in controller action - c#

public ActionResult SomeAction(int?id)
{
MyModel model = new MyModel();
return View(model);
}
[Test]
public void Can_Open_SomeAction()
{
// controller is already set inside `SetUp` unit step.
ViewResult res = this.controller.SomeAction() as ViewResult;
var model = result.Model as MyModel;
Assert.IsNotNull(model);
}
this test passes succ. but when when change controller action to have populate combos like
public ActionResult SomeAction(int?id)
{
MyModel model = new MyModel();
this.PopulatePageCombos(id);
return View(model);
}
I'm getting error on line this.PopulatePageCombos(id);
Object reference is not set
So, how can I mock this PopulatePageCombos method in unit test?
Update:
public ActionResult SomeAction(int?id)
{
MyModel model = new MyModel();
this.PopulatePageCombos(model.Id, 100);
return View(model);
}
Update 2:
PopulatePageCombos (model, countryId, requesterId);
where model is of type MyModel, countryId is int and requesterId is int

You can create a helper class PopulatePageCombosHelper and encapsulate PopulatePageCombos method in it. So the SomeAction method would look like
public PopulatePageCombosHelper populatePageHelper;
public ActionResult SomeAction(int?id)
{
MyModel model = new MyModel();
populatePageHelper.PopulatePageCombos(id);
return View(model);
}
So then you can mock populatePageHelper
[Test]
public void Can_Open_SomeAction()
{
// controller is already set inside `SetUp` unit step.
var populatePageHelperMock = new Mock<PopulatePageCombosHelper>();
controller.populatePageHelper = populatePageHelperMock;
ViewResult res = this.controller.SomeAction() as ViewResult;
var model = result.Model as JobCreate;
//...
Assert.IsNotNull(model);
}

You can make PopulatePageCombos method virtual and override it in derived class ControllerTestable and test the ControllerTestable
public class ControllerTestable : Controller
{
public bool IsCalled = false;
public override ViewResult SomeAction()
{
IsCalled = true;
return null;
}
}
So in the test instead of creating Controller controller you can create ControllerTestable controller.
[Setup]
public void SetUp ()
{
var controller = new ControllerTestable();
//...
}
[Test]
public void Can_Open_SomeAction()
{
// controller is already set inside `SetUp` unit step.
ViewResult res = this.controller.SomeAction() as ViewResult;
var model = result.Model as JobCreate;
//...
Assert.IsTrue(controller.IsCalled);
Assert.IsNotNull(model);
}

You can partial mock the controller. Having:
public virtual void PopulatePageCombos(int? id)
{
throw new NullReferenceException();
}
public ActionResult SomeAction(int? id)
{
MyModel model = new MyModel();
this.PopulatePageCombos(id);
return View(model);
}
Then you setup the method PopulatePageCombos to do anything:
public class Default1ControllerTests
{
private Mock<Default1Controller> controllerMock;
[SetUp]
public void SetUp()
{
this.controllerMock = new Mock<Default1Controller>() { CallBase = true };
this.controllerMock.Setup(m => m.PopulatePageCombos(It.IsAny<int?>())).Callback(() => { });
}
[Test]
public void Can_Open_SomeAction()
{
// controller is already set inside `SetUp` unit step.
ViewResult res = this.controllerMock.Object.SomeAction(null) as ViewResult;
var model = res.Model as MyModel;
Assert.IsNotNull(model);
}
}
It's important to declare virtual the method to mock and specify CallBase = true on mock creation. This will call the programmed logic on methods not setup.

Related

How to Moq an update method in controller

I am trying to mock a method that updates an entry into the database using EF.
class MyController
{
private readonly IEmployeeRepository;
private readonly IProjectRepository;
MyController(IEmployeeRepository employeeRepository,IProjectRepository projectRepository)
{
_employeeRepository=employeeRepository;
_projectRepository=projectRepository;
}
public async Task<IHttpActionResult> ExtendEmployeeContract(int employeeId, int projectId)
{
var projectModel=_projectRepository.GetProjectDetails(projectId);
int result=-1;
if(projectMode !=null)
{
bool isprojectactive=projectMode.IsActive;
// Some made-up function that is setting the IsContractActive value to true/false
result=_employeeRepository.ExtendContract
(new EmployeeModel(){Id = employeeId,IsContractActive = isprojectactive};);
}
return Ok(new ResponseModel(){Data=result});
}
}
[TestClass]
class MyControllerTestClass
{
private Mock<IEmployeeRepository> _mockedEmployeeRepository;
private Mock<IProjectRepository> _mockedProjectRepository;
ProjectModel _projectModel;
EmployeeModel _empModel;
[TestInitialize]
public void TestInitialize()
{
_mockedEmployeeRepository = new Mock<IEmployeeRepository>();
_mockedProjectRepository = new Mock<IProjectRepository>();
_projectModel = new ProjectModel()
{
Id = 5678,
Name = "testProject",
IsActive=true;
};
_empModel = new EmployeeModel()
{
Id = 123,
IsContractActive = false
};
}
[TestMethod]
public async Task ExtendEmployeeContract_ShouldUpdateAndExtend_EmployeeContract()
{
// Arrange
_mockedProjectRepository.Setup(x=>x.GetProjectDetails(5678)).Returns(_projectModel);
_mockedEmployeeRepository.Setup(x=>x.ExtendContract(_empModel)).Returns(1);
// Act
var mycontroller=new MyController(_mockedEmployeeRepository.object,_mockedProjectRepository.object);
var actionResult = await mycontroller.ExtendEmployeeContract(123,5678) as OkNegotiatedContentResult<ResponseModel>;
// Assert
Assert.AreEqual(1,Convert.ToInt(actionResult.Content.Data.ToString());
}
}
I am trying to mock this controller in my test class . I can successfully mock GetProjectDetails method but I cant mock ExtendContract. I debugged the ExtendEmployeeContract method and found that _employeeRepository.ExtendContract always returns 0
Your fake setup is wrong. Even though you are passing your EmployeeModel
_mockedEmployeeRepository.Setup(x=>x.ExtendContract(_empModel)).Returns(1);
In your controller code you are creating new Employee model, which is different from what you pass in test
result=_employeeRepository.ExtendContract
(new EmployeeModel(){Id = employeeId,IsContractActive = isprojectactive};);
Your fake setup should look like:
_mockedEmployeeRepository.Setup(x=>x.ExtendContract(It.IsAny<EmployeeModel>())).Returns(1);

How to mock viewModel when test controller?

I have to test my controller as below
[HttpGet]
[Route("")]
[HandleError(View= "Error")]
public ActionResult Index(string name)
{
return View("Index", new MyViewModel){
Name = name,
Link = Request.UrlReferrer
}
}
and my ViewModel is as below
public class MyViewModel{
public string Name{get;set;}
public Uri Link{get;set}
}
My problem is, when I write a unit test as below, the controller.Index(name) always return null, it seems because I didn't mock ViewModel? But how I mock the ViewModel as it is inside the function?
My purpose is to test if the name is passed into the ViewModel properly, I think I should not mock MyViewModel, is that correct?
Also, as this is HttpGet, should I mock the Http Request? I'm not sure how to test the Http Request in MVC.NET
[TestMethod]
public void Index_Return_ViewModel(){
string name = "name";
var controller = new MyController(foo, bar);
var result = controller.Index(name) as ViewResult;
var viewModel = controller.ViewData.Model as MyViewModel;
Assert.AreEqual("Index", result.ViewName);
}
Using the following example controller
public class MyController : Controller {
[HandleError(View = "Error")]
public ActionResult Index(string name) {
return View("Index", new MyViewModel() {
Name = name,
Link = Request.UrlReferrer
});
}
}
for the purposes of explaining the answer.
Because the action accesses the Request.UrlReferrer, the unit test would need to provide the necessary dependencies for the test to be exercised to completion.
For example
[TestMethod]
public void Index_Return_ViewModel() {
//Arrange
var link = new Uri("http://example.com");
var mockContext = new Mock<ControllerContext>();
mockContext.Setup(_ => _.HttpContext.Request.UrlReferrer)
.Returns(link);
string name = "name";
var controller = new MyController() {
ControllerContext = mockContext.Object
};
//Act
var result = controller.Index(name) as ViewResult;
//Assert
Assert.AreEqual("Index", result.ViewName);
var viewModel = controller.ViewData.Model as MyViewModel;
Assert.IsNotNull(viewModel);
Assert.AreEqual(name, viewModel.Name);
Assert.AreEqual(link, viewModel.Link);
}
There was no need to mock the view model. The action can be confirmed to behave as expected by comparing the returned model properties to the expected values.

Asp.Net MVC 5 Testing IoC + Dependency Injection

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.

How to Unit Test a GlassController Action which Returns a View Taking a Model

I'm a sitecore developer and I want to create a sample sitecore helix unit testing project for testing out our "HomeBottomContentController" controller:
public class HomeBottomContentController : GlassController
{
private readonly ISitecoreContext _iSitecoreContext;
public HomeBottomContentController(ISitecoreContext iSitecoreContext)
{
_iSitecoreContext = iSitecoreContext;
}
public override ActionResult Index()
{
var model = _iSitecoreContext.GetCurrentItem<Home_Control>();
return View("~/Views/HomeBottomContent/HomeBottomContent.cshtml", model);
}
}
I have created a WTW.Feature.HomeBottomContent.Tests project, for the purpose of testing this entire component using helix unit testing. In it I have a UnitTest1.cs file with following:
namespace WTW.Feature.HomeBottomContent.Tests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void Test_ISitecoreContextInsertion()
{
var iSitecoreContext = Mock.Of<Glass.Mapper.Sc.ISitecoreContext>();
HomeBottomContentController controllerUnderTest = new HomeBottomContentController(iSitecoreContext);
var result = controllerUnderTest.Index() as ViewResult;
Assert.IsNotNull(result);
}
}
}
This test does pass, meaning "result" is NOT null; however, the problem is when I step into the Index() code, I see that the "model" variable is NULL when we do
var model = _iSitecoreContext.GetCurrentItem<Home_Control>();
My question is, how exactly do I change this code to make sure that the "model" in that line does not become null? How do I "mock" an item in unit test code for the _iSitecoreContext so that it has a "Home_Control" template with legit values for its fields? Would that even be the right approach? Most online sources I've found do not have a similar scenario, I'm looking for the shortest code possible.
Another question I had is, how can I test the below Index() method in my [TestMethod], given that the SitecoreContext is declared inside the Index() method, rather than received in the HomeBottomContentController constructor like above? Is there a way to do that from the [TestMethod], or we have to send in the SitecoreContext into the HomeBottomContentController constructor or into the Index() method as a parameter?
public override ActionResult Index()
{
var context = new SitecoreContext();
var model = context.GetCurrentItem<Home_Control>();
return View("~/Views/HomeBottomContent/HomeBottomContent.cshtml", model);
}
In that case you would need to mock the desired behavior on the mocked dependency
[TestClass]
public class UnitTest1 {
[TestMethod]
public void Test_ISitecoreContextInsertion() {
//Arrange
var model = new Home_Control() {
//...populate as needed
}
var iSitecoreContext = new Mock<Glass.Mapper.Sc.ISitecoreContext>();
//Setup the method to return a model when called.
iSitecoreContext.Setup(_ => _.GetCurrentItem<Home_Control>()).Returns(model);
var controllerUnderTest = new HomeBottomContentController(iSitecoreContext.Object);
//Act
var result = controllerUnderTest.Index() as ViewResult;
//Assert
Assert.IsNotNull(result);
Assert.IsNotNull(result.Model);
//...other assertions.
}
}
UPDATE
Creating the context within the action tightly couples it to the context, making it almost impossible to mock. That is the reason explicit dependencies are injected
You can do something like that:
public class HomeBottomContentController : GlassController
{
private readonly ISitecoreContext _iSitecoreContext;
public HomeBottomContentController(ISitecoreContext iSitecoreContext)
{
_iSitecoreContext = iSitecoreContext;
}
public override ActionResult Index()
{
var model = this.GetCurrentItem();
return View("~/Views/HomeBottomContent/HomeBottomContent.cshtml", model);
}
protected virtual Home_Control GetCurrentItem()
{
return _iSitecoreContext.GetCurrentItem<Home_Control>();
}
}
namespace WTW.Feature.HomeBottomContent.Tests
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void Test_ISitecoreContextInsertion()
{
var iSitecoreContext = Mock.Of<Glass.Mapper.Sc.ISitecoreContext>();
var controllerUnderTest = new FakeHomeBottomContentController(iSitecoreContext);
var result = controllerUnderTest.Index() as ViewResult;
Assert.IsNotNull(result);
}
}
public class FakeHomeBottomContentController : HomeBottomContentController
{
public FakeHomeBottomContentController(ISitecoreContext iSitecoreContext) : base(iSitecoreContext)
{
}
protected override Home_Control GetCurrentItem()
{
// return instance of Home_Control type
// e.g.
return new Home_Control();
}
}
}

How to Unit test a method using Moqs which create session

How to test a method which creates session inside the method. i using to do Unit test . when i call method using test case it was unable to create session inside method. can anyone please help me to create unit tests for my code below
public ActionResult InviteUser(string Id)
{
if (!string.IsNullOrEmpty(Id))
{
Session["verification_uid"] = Id;
return RedirectToAction("Login", "Account");
}
return View();
}
i have tried with following code also but it not working
[TestMethod]
public void InviteUser_ExpectRedirectActionResultReturned()
{
//Arrange
controller = new AccountController();
var mockControllerContext = new Mock<ControllerContext>();
var mockSession = new Mock<HttpSessionStateBase>();
mockSession.SetupGet(s => s["verification_uid"]).Returns("123"); //somevalue
mockControllerContext.Setup(p => p.HttpContext.Session).Returns(mockSession.Object);
controller.ControllerContext = mockControllerContext.Object;
var id = "1";
System.Web.HttpContext.Current.Session["verification_uid‌​ID"] = "12";
//Act
var result = (RedirectToRouteResult)controller.InviteUser(id);
//Assert
result.RouteValues["action"].Equals("Index");
result.RouteValues["controller"].Equals("Home");
Assert.AreEqual("Index", result.RouteValues["action"]);
Assert.AreEqual("Home", result.RouteValues["controller"]);
}
You could put the setting of the session variable into a helper class, implementing an interface that gets passed into the class which you could mock in the unit test.
public MyClass
{
private readonly ISessionHelper _helper;
public MyClass(ISessionHelper helper)
{
this._helper = helper;
}
public ActionResult InviteUser(string Id)
{
if (!string.IsNullOrEmpty(Id))
{
this._helper.SetSessionVariable("verification_uid", Id);
return RedirectToAction("Login", "Account");
}
return View();
}
}
Your helper would contain SetSessionVariable which does the setting.
Then, in your unit test, you mock ISessionHelper.

Categories