I am trying to set basic MOQ testing for my CRUD routes controller. Our application is fairly small and we want to establish basic testing first before we move into more advance testing (using fakes and what not).
This is my current test page:
[TestClass()]
public class AdminNotesTest
{
[TestMethod]
public void CreatingOneNote()
{
var request = new Mock<HttpRequestBase>();
request.Setup(r => r.HttpMethod).Returns("POST");
var mockHttpContext = new Mock<HttpContextBase>();
mockHttpContext.Setup(c => c.Request).Returns(request.Object);
var controllerContext = new ControllerContext(mockHttpContext.Object, new RouteData(), new Mock<ControllerBase>().Object);
var adminNoteController = new AdminNotesController();
adminNoteController.ControllerContext = controllerContext;
var result = adminNoteController.Create("89df3f2a-0c65-4552-906a-08bceabb1198");
Assert.IsNotNull(result);
}
[TestMethod]
public void DeletingNote()
{
var controller = new AdminNotesController();
}
}
}
Here you will be able to see my controller method I am trying to hit and create a note.
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(AdminNote adminNote)
{
try
{
if (ModelState.IsValid)
{
adminNote.AdminKey = System.Web.HttpContext.Current.User.Identity.GetUserId();
adminNote.AdminName = System.Web.HttpContext.Current.User.Identity.GetUserName();
adminNote.CreateDate = DateTime.Now;
adminNote.ModifiedDate = DateTime.Now;
adminNote.ObjectState = ObjectState.Added;
_adminNoteService.Insert(adminNote);
return RedirectToAction("UserDetails", "Admin", new { UserKey = adminNote.UserKey });
}
}
catch (Exception ex)
{
ControllerConstants.HandleException(ex);
ViewBag.PopupMessage(string.Format("We're sorry but an error occurred. {0}", ex.Message));
}
return View(adminNote);
}
I know that in order for my create method to work I will need to provide the method with a AdminKey and an AdminName. I dont want to hit the database for any of these tests and I have read that this is actually possible I dont have a lot of experience and was wondering if someone could guide me in this process as to what would be the best way to approach this and provide this info.
Thanks for all the help guys and I do hope that after this question I can get better at unit testing.
I believe what you trying to achieve is to get some direction on writing a Unit Test around Create Action. And you don't want to hit the database. You also want this to be simple and don't want to use advanced Fakes.
There are few tests you may write here. Below are some scenarios you may want to think. a. Whether the AdminService.Insert Method on the adminNoteService is called.
b. Whether the AdminService.Insert method called with expected parameters
c. RedirectToAction method return the expected type of result.
d. When an exception being thrown whether the exeception has been thrown with correct message, exception type etc.
e. Verify certain calls when the Model state is valid.
There are few tests you can write, but below is an example to get you started.
First thing I would do is to be very clear on what you trying to Unit Test. The way you express this in your test method name. Let's say we want to target the 'c'
Instead of a test method like "CreatingOneNote" I would prefer a test method name like below..
I would make the following changes to your SUT/Controller (System Under Test)
As you have noticed a. I don't use the real system date time, instead I use DateTime Delegate. This allows me to provide a fake date time during testing. In the real production code it will use real system date time.
b. Instead of useing HttpContext.Current.. you can use ControllerContext.HttpContext.User.Identity. This will allow you to stub our the HttpConext and ControllerContext then User and Identity. Please see the test below.
This test can be simplify a lot if you are familiar advanced Unit Testing concepts such as AutoMocking. But for the time being, I'm sure this will point you to the right direction.