I recently started learning Unit Test in MVC and used NUnit Framework for Test Cases. My problem is, i cannot understand for what should i write Test case. Imagine i have CRUD operation and i want to Test them, so what should be my Test case condition.
Here is my Interface class:
public interface IUserRepository
{
//Creating Single User Records into database using EF.
bool CreateUser(tbl_Users objUser);
//Updating Single User Records into database using EF.
void UpdateUser(tbl_Users objUser);
//Deleting Single User Records from database using EF.
bool DeleteUser(long IdUser);
}
Here is my Repository Class:
public class UserRepository : IUserRepository
{
DBContext objDBContext = new DBContext();
/// <summary>
/// Creating new User Record into Database
/// </summary>
/// <param name="objUser"></param>
public bool CreateUser(tbl_Users objUser)
{
bool blnResult = false;
objUser.MiddleName = string.IsNullOrEmpty(objUser.MiddleName) ? string.Empty : objUser.MiddleName.Trim();
objUser.Photo = string.Empty;
objUser.Approved = false;
objUser.CreatedDate = DateTime.Now;
objUser.DeleteFlag = false;
objUser.UpdBy = 0;
objUser.UpdDate = DateTime.Now;
objDBContext.tbl_Users.Add(objUser);
blnResult = Convert.ToBoolean(objDBContext.SaveChanges());
return blnResult;
}
/// <summary>
/// Updating existing User Record into Database
/// </summary>
/// <param name="objUser"></param>
public void UpdateUser(tbl_Users objUser)
{
objUser.MiddleName = string.IsNullOrEmpty(objUser.MiddleName) ? string.Empty : objUser.MiddleName.Trim();
objUser.Approved = true;
objUser.UpdBy = objUser.IdUser;
objUser.UpdDate = DateTime.Now;
objDBContext.Entry(objUser).State = EntityState.Modified;
objDBContext.SaveChanges();
}
/// <summary>
/// Deleting existing User Record from Database
/// </summary>
/// <param name="IdUser"></param>
public bool DeleteUser(long IdUser)
{
bool blnResult = false;
tbl_Users objUser = objDBContext.tbl_Users.Where(x => x.IdUser == IdUser).Single();
objUser.ConfirmPassword = objUser.Password;
objUser.UpdDate = DateTime.Now;
objUser.DeleteFlag = true;
blnResult = Convert.ToBoolean(objDBContext.SaveChanges());
return blnResult;
}
}
And Here is My Controller class
public class UserController : Controller
{
tbl_Users objUser = new tbl_Users();
UserRepository Repository = new UserRepository();
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult Create(tbl_Users objUser)
{
if (ModelState.IsValid)
{
try
{
Repository.CreateUser(objUser);
return RedirectToAction("Update", "User");
}
catch
{
return View();
}
}
return View();
}
[ValidateAntiForgeryToken]
[HttpPost]
public ActionResult Update(tbl_Users objUser)
{
Repository.UpdateUser(objUser);
return View();
}
public ActionResult Delete(long IdUser = 0)
{
bool blnResult = Repository.DeleteUser(IdUser);
if (blnResult)
{
return View("Delete");
}
else
{
return View();
}
}
}
Here are Test cases which i tried to Execute using Moq
[TestFixture]
public class UserControllerTest
{
UserController Controller;
[SetUp]
public void Initialise()
{
Controller = new UserController();
}
[Test]
public void DeleteTest()
{
var ObjUser = new Mock<IUserRepository>();
ObjUser.Setup(X => X.DeleteUser(It.IsAny<long>())).Returns(true);
var Result = ObjUser.Object.DeleteUser(1);
Assert.That(Result, Is.True);
}
[Test]
public void CreateTest()
{
tbl_Users User = new tbl_Users();
Mock<IUserRepository> MockIUserRepository = new Mock<IUserRepository>();
MockIUserRepository.Setup(X => X.CreateUser(It.IsAny<tbl_Users>())).Returns(true);
var Result = MockIUserRepository.Object.CreateUser(User);
Assert.That(Result, Is.True);
}
[TearDown]
public void DeInitialise()
{
Controller = null;
}
}
Can anyone tell me, how to Write test cases for above Controller Action Method with brief description about test cases using Moq.
you have a couple of problems. the first is that you have not tested your controller, you have tested your mock. The second is that your controller creates it's own user repository. this means that you can't provide a mock user repository in order to test, even if you were testing it.
The solution to the first on is to test the controller, by calling its methods and asserting the results, however you'll have solve the second one before you can do that in your tests.
To solve the second one you'll need to apply the dependency inversion principal and pass your IUserRepository implementation into your controller (via the constructor ideally).
you could change your controller to have a constructor like this:
public class UserController : Controller
{
tbl_Users objUser = new tbl_Users();
IUserRepository Repository;
public UserController(IUserRepository userRepository)
{
Repository = userRepository;
}
...etc
}
then you can change your tests to be more like this:
[TestFixture]
public class UserControllerTest
{
[Test]
public void DeleteTest()
{
var ObjUser = new Mock<IUserRepository>();
ObjUser.Setup(X => X.DeleteUser(It.IsAny<long>())).Returns(true);
var Result = new UserController(ObjUser.Object).Delete(1);
Assert.That(Result, //is expected view result with expected model);
Assert.That(ObjUser.Verify(), Is.True);
}
[Test]
public void CreateTest()
{
tbl_Users User = new tbl_Users();
Mock<IUserRepository> MockIUserRepository = new Mock<IUserRepository>();
MockIUserRepository.Setup(X => X.CreateUser(It.IsAny<tbl_Users>())).Returns(true);
var Result = var Result = new UserController(ObjUser.Object).Create(User);;
Assert.That(Result, //is a view result with expected view model);
Assert.That(ObjUser.Verify(), Is.True);
}
}
now you are testing the actual controller and checking it returns the right view and that it interacts with the mock repository in the expected way
Related
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);
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'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 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_uidID"] = "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.
I'm trying to test a method, which relies on the value of one of the fields in my model (used as a parameter). I'm looking for help on how to mock this value, so my unit test will work.
Without setting this value, the test will follow the path to the exception.
CONTROLLER
public class StatusViewerController : Controller
{
private IERERepository _ereRepository;
//Dependency Injection
public StatusViewerController(IERERepository ereRepository)
{
_ereRepository = ereRepository;
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit([Bind(Include = "RecordID,ClientNumber")] StatusViewerFormViewModel model)
{
if (ModelState.IsValid)
{
try
{
//Send to one of two functions depending on RecordID value
if (model.RecordID == null)
{
_ereRepository.StatusViewerInsert(model);
}
else
{
_ereRepository.StatusViewerUpdate(model);
}
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
catch
{
throw new HttpException(500, "Internal Server Error");
}
}
else
{
throw new HttpException(400, "ModelState Invalid");
}
}
}
UNIT TEST
/// <summary>
/// Tests the Edit method for ActionResult return type
/// </summary>
[TestMethod]
public void StatusViewer_Edit_Returns_ActionResult()
{
//Arrange
var mockRepository = new Mock<IERERepository>();
StatusViewerController controller = new StatusViewerController(mockRepository.Object);
//Act
//I need to set the value of RecordID here or else this test will fail
//It will return an exception
ActionResult result = controller.Edit(It.IsAny<StatusViewerFormViewModel>());
//Assert
Assert.IsInstanceOfType(result, typeof(ActionResult));
}
Just create the model and call the method under test.
What you have not done is setup your dependency for the controller.
/// <summary>
/// Tests the Edit method for ActionResult return type
/// </summary>
[TestMethod]
public void StatusViewer_Edit_Returns_ActionResult()
{
//Arrange
var mockRepository = new Mock<IERERepository>();
mockRepository
.Setup(m => m.StatusViewerInsert(It.IsAny<StatusViewerFormViewModel>())
.Verifiable();
var controller = new StatusViewerController(mockRepository.Object);
var model = new StatusViewerFormViewModel {
RecordID = "set the value of RecordID here",
ClientNumber = "Other property value here",
//...other properties
};
//Act
ActionResult result = controller.Edit(model);
//Assert
Assert.IsInstanceOfType(result, typeof(ActionResult));
mockRepository.Verify();//verify that the repository was called.
}