I am using Sharp Architechture and Rhino Mocks with NUnit.
I have a test service that looks like this
public class TestService : ITestService {
public TestService(ITestQueries testQueries, IRepository<Test> testRepository,
IApplicationCachedListService applicationCachedListService) {
Check.Require(testQueries != null, "testQueries may not be null");
Check.Require(applicationCachedListService != null, "applicationCachedListService may not be null");
_testQueries = testQueries;
_testRepository = testRepository;
_applicationCachedListService = applicationCachedListService;
}
I then have this method in my service
public string Create(TestFormViewModel viewModel, ViewDataDictionary viewData, TempDataDictionary tempData) {
if (!viewData.ModelState.IsValid) {
tempData.SafeAdd(viewModel);
return "Create";
}
try {
var test = new Test();
UpdateFromViewModel(test, viewModel);
_testRepository.SaveOrUpdate(test);
tempData[ControllerEnums.GlobalViewDataProperty.PageMessage.ToString()]
= string.Format("Successfully created product '{0}'", test.TestName);
}
catch (Exception ex) {
_testRepository.DbContext.RollbackTransaction();
tempData[ControllerEnums.GlobalViewDataProperty.PageMessage.ToString()]
= string.Format("An error occurred creating the product: {0}", ex.Message);
return "Create";
}
return "Index";
}
}
I then have a Controller that looks like this:
[ValidateAntiForgeryToken]
[Transaction]
[AcceptVerbs(HttpVerbs.Post)]
[ModelStateToTempData]
public ActionResult Create(TestFormViewModel viewModel) {
return RedirectToAction(_testService.Create(viewModel, ViewData, TempData));
}
I want to write a simple test to see if when !viewData.ModelState.IsValid I return "Create".
I have this so far but am confused because it really is not testing the controller it is just doing what I am telling it to do in the return.
[Test]
public void CreateResult_RedirectsToActionCreate_WhenModelStateIsInvalid(){
// Arrange
var viewModel = new TestFormViewModel();
_controller.ViewData.ModelState.Clear();
_controller.ModelState.AddModelError("Name", "Please enter a name");
_testService.Stub(a => a.Create(viewModel, new ViewDataDictionary(), new TempDataDictionary())).IgnoreArguments().Return("Create");
// Act
var result = _controller.Create(viewModel);
// Assert
result.AssertActionRedirect().ToAction("Create"); //this is really not testing the controller??.
}
Any help is appreciated.
It looks like you try to write not Unit tests. It's more like Integration test. Following Unit-testing ideology you have two Units:
Service
andController
. The idea is that you should test each unit separately and keep your tests simple. According this first of all you should write tests forTestService
. After that, when you cover it, write tests for yourController
using Stubs/Mocks forTestService
. So your test forController
looks right, it tests that redirect is happened according to result fromService.Create
method. You should add tests for yourTestService
without controller context and it's got a good coverage. If you want to test this units together then you must not use mocks and it will be more like Integration tests. Additionally to cover integration between modules you can write web based tests using some tools like WatiN or Selenium for testing whole application. But in any case write unit tests for separate parts is a good practice.