Rhino Mocks: Stubbing an IEnumerator<T> - c#-2.0

I'm developing a little .net 2.0 project. I get to the point where I need to test some class's method which takes an IEnumerator. As a few days ago I learnt to use Rhino Mocks I wrote the following test
[Test]
public void GetEnumerator_ValidList_ReverseIteration()
{
MockRepository mMocks = new MockRepository();
IEnumerator<string> mStubEnumerator = mMocks.Stub<IEnumerator<string>>();
IProcessCommandFactory mStubFactory = mMocks.Stub<IProcessCommandFactory>();
using (mMocks.Record())
{
mStubEnumerator.MoveNext();
LastCall.Return(true);
Expect.Call(mStubEnumerator.Current);
LastCall.Return("Organization");
mStubEnumerator.MoveNext();
LastCall.Return(true);
Expect.Call(mStubEnumerator.Current);
LastCall.Return("Algorithm");
mStubEnumerator.MoveNext();
LastCall.Return(true);
Expect.Call(mStubEnumerator.Current);
LastCall.Return("ProcessTemplate");
mStubEnumerator.MoveNext();
LastCall.Return(false);
}
DeleteStrategy mStrategy= new DeleteStrategy( mStubFactory,
"S1",
true);
mStrategy.Load(mStubEnumerator);
... meaningless code...
}
this is the method code
public void Load(IEnumerator<string> pProcessCommmandNames)
{
while (pProcessCommmandNames.MoveNext())
{
string bCommandName= pProcessCommmandNames.Current;
... doing something with the string...
}
}
When I try to run the, it won't stop since it uses only the first MoveNext() injected value and starts a loop.
I would appreciated if someone could poit me out what I'm doing wrong?
Thanks

From what I am seeing you are passing Load() the stub mStubEnumerator. With out setting any of the properties on the stub, all of the methods are going to do nothing and all of the properties are going to return null.
Here is a great article by Martin Fowler reviewing the differences between Mocks, Stubs, and Fakes.
So to make this test work, I would consider using a fake:
MockRepository mMocks = new MockRepository();
IEnumerator<string> mFakeEnumerator = new List<string>();
mFakeEnumerator.Add("Organization");
mFakeEnumerator.Add("Algorithm");
mFakeEnumerator.Add("ProcessTemplate");
IProcessCommandFactory mStubFactory = mMocks.Stub<IProcessCommandFactory>();
...
Now I am guessing that the test will pass, or it will be closer to passing.
Without seeing more of the code, however, I cannot be sure that it would be effectively testing what you set out to achieve.

If you just need an IEnumerator<String>, there's no need to create a mock. Simply create a List<String> and pass in it's enumerator:
var commandNames = new List<String> {"one", "two", "three"};
DoSomething(commandNames.GetEnumerator());

Related

Autofac and HostingEnvironment.QueueBackgroundWorkItem

I'm looking to add some background processing to my ASP.NET MVC 5 application, more specifically executing some long-ish (5-10 seconds) running tasks with HostingEnvironment.QueueBackgroundWorkItem. Now, the problem that I'm having is that code is running "out of band" and is not tied to the request any more - Autofac disposes of some of the injected dependencies.
Here is some of the code:
[HttpPost, ActionName("Execute")]
public ActionResult ExecutePost(Guid taskguid, FormCollection values)
{
if (taskguid == default(Guid))
{
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
var model = _taskListService.GetTaskByGuid(taskguid);
if (TryUpdateModel(model.TaskObject as MissingCrossReferenceTask))
{
model.TaskObject.DependencyContainer = _dependencyContainer;
model.TaskObject.TaskListId = model.Id;
HostingEnvironment.QueueBackgroundWorkItem(ct => ExecuteTask(ct, model));
return RedirectToAction("Index", "Dashboard");
}
return View(model);
}
In the code above DependencyContainer is an object that contains a number of dependencies that are injected by Autofac (EF Repositories and Services)
private void ExecuteTask(CancellationToken ct, TaskList model)
{
model.TaskObject.Execute();
}
Inside of that execute method of the MissingCrossReferenceTask (which is in a separate assembly from the ASP.NET MVC project:
public bool Execute()
{
long tableId = DependencyContainer.CrossReferenceService.GetCrossReferenceTable(TableName).Id;
string currentValue = DependencyContainer.CrossReferenceService.GetValue(FromValue, tableId);
...
}
The first line throws an exception: ObjectDisposedExcetion {"The ObjectContext instance has been disposed and can no longer be used for operations that require a connection."}
Now, I don't know the Autofac well enough to figure out the best way around this. Is it somehow possible to re-inject the reference directly in ExecuteTask method? If so - how?
I would extremely appreciate any help of this. It has been driving me insane for a few days now...
Thanks,
Nick Goloborodko
I guess submitting the question has forced me to look at the problem from a slightly different angle.
I think I have found a way around this (in other words - it now works as I'd like it to). I'm still not sure if this approach is the best in my situation or if there are any unseen problems with it - I would much appreciate any comments around this topic!
I have solved the issue in the following way:
private void ExecuteTask(CancellationToken ct, TaskList model)
{
MvcApplication app = this.HttpContext.ApplicationInstance as MvcApplication;
using (var container = app.ContainerProvider.ApplicationContainer.BeginLifetimeScope(WebLifetime.Application))
{
model.TaskObject.DependencyContainer = container.Resolve<DependencyContainer>();
model.TaskObject.Execute();
}
}
(adopted from a solution posted on this page: http://aboutcode.net/2010/11/01/start-background-tasks-from-mvc-actions-using-autofac.html)
Hope this may save a bit of time to someone else in the future!

How to Unit Test JsonResult and Collections in MSTest

I am very new to unit testing even though i have been coding for a very long time. I want to make this a part of my way of development. I run into blocks on how to unit test things like a collection. I generally have my jQuery script calling ASP.Net Server side methods to get data and populate tables and the like. They look like
Get_*Noun*()
which generally returns a JsonResult. Any ideas on what and how to test these using Unit tests using MSTest?
You should be able to test this just like anything else, provided you can extract the values from the JsonResult. Here's a helper that will do that for you:
private T GetValueFromJsonResult<T>(JsonResult jsonResult, string propertyName)
{
var property =
jsonResult.Data.GetType().GetProperties()
.Where(p => string.Compare(p.Name, propertyName) == 0)
.FirstOrDefault();
if (null == property)
throw new ArgumentException("propertyName not found", "propertyName");
return (T)property.GetValue(jsonResult.Data, null);
}
Then call your controller as usual, and test the result using that helper.
var jsonResult = yourController.YourAction(params);
bool testValue = GetValueFromJsonResult<bool>(jsonResult, "PropertyName");
Assert.IsFalse(testValue);
(I am using NUnit syntax, but MSUnit shouldn't be far off)
You could test your JsonResult like this:
var json = Get_JsonResult()
dynamic data = json.Data;
Assert.AreEqual("value", data.MyValue)
Then in the project that contains the code to be tested, edit AssemblyInfo.cs file to allow the testing assembly access to the anonymous type:
[assembly: InternalsVisibleTo("Tests")]
This is so the dynamic can determine the type of anonymous object being returned from the json.Data value;
This is the best blog I've found on this subject.
My favorite was the 4th approach using dynamics. Note that it requires you to ensure that the internals are visible to your test project using [assembly:InternalsVisibleTo("TestProject")] which I find is a reasonably good idea in general.
[TestMethod]
public void IndexTestWithDynamic()
{
//arrange
HomeController controller = new HomeController();
//act
var result = controller.Index() as JsonResult;
//assert
dynamic data = result.Data;
Assert.AreEqual(3, data.Count);
Assert.IsTrue(data.Success);
Assert.AreEqual("Adam", data.People[0].Name);
}
You could use PrivateObject to do this.
var jsonResult = yourController.YourAction(params);
var success = (bool)(new PrivateObject(jsonResult.Data, "success")).Target;
Assert.IsTrue(success);
var errors = (IEnumerable<string>)(new PrivateObject(jsonResult.Data, "errors")).Target;
Assert.IsTrue(!errors.Any());
It's uses reflection similar to David Ruttka's answer, however it'll save you a few key strokes.
See http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.privateobject.aspx for more info.
Here's a small extension to easily convert a Json ActionResult into the object it represents.
using System.Web.Mvc;
public static class WebExtensions
{
public static T ToJson<T>(this ActionResult actionResult)
{
var jsonResult = (JsonResult)actionResult;
return (T)jsonResult.Data;
}
}
With this, your 'act' in the test becomes smaller:
var myModel = myController.Action().ToJson<MyViewModel>();
My suggestion would be to create a model for the data returned and then cast the result into that model. That way you can verify:
the structure is correct
the data within the model is correct
// Assert
var result = action
.AssertResultIs<JsonResult>();
var model = (UIDSearchResults)result.Data;
Assert.IsTrue(model.IsValid);
Assert.AreEqual("ABC", model.UIDType);
Assert.IsNull(model.CodeID);
Assert.AreEqual(4, model.PossibleCodes.Count());

Unit testing ensure one method calls another method

[HttpPost]
public ActionResult Create(Car car)
{
_repository.CreateCar(car);
_repository.UpdateRegistrationDetails(car);
}
What I'm wanting to do is write unit test to ensure that Create calls CreateCar and UpdateRegistrationDetails. It doesn't matter about what happens in these methods but just that they get called. Could someone please tell me how to do this? Do I need to use a mocking framework for this? I have RhinoMocks installed to use. Do you use the Expect in RhinoMocks?
Again using Moq I think you need to mock the Repository instead (assuming names here of course)
var mock = new Mock<IRepository>();
var controller = new Controller(mock.Object); //assuming this is how you create it
var car = new Car();
controller.Create(car);
mock.Verify(x => x.CreateCar(car));
mock.Verify(x => x.UpdateRegistrationDetails(car));
No need for Setup or Expect as the mocked methods do not return anything
[EDIT]
Here is a Rhino.Mocks example
var mock = MockRepository.GenerateStub<IRepository>();
var controller = new Controller(mock); //assuming this is how you create it
var car = new Car();
controller.Create(car);
mock.AssertWasCalled(x => x.CreateCar(car));
mock.AssertWasCalled(x => x.UpdateRegistrationDetails(car));
The best answer is to use a mocking framework as others here have mentioned. The dirty way, but sometimes faster if you don't want to learn mocking frameworks (which you really should) is to create a test class and override virtual methods. In your case something like
public class RepoUnderTest : Repo
{
public bool UpdateRegistrationDetailsCalled = false;
public override void UpdateRegistrationDetails(Car car)
{
base.UpdateRegistrationDetails(car);
UpdateRegistrationDetailsCalled = true;
}
}
then you can test something similar to
[HttpPost]
public ActionResult Create(Car car)
{
// Arrange
var _repository = new RepoUnderTest();
// Act
_repository.CreateCar(car);
// Assert
Assert.IsTrue(_repository.UpdateRegistrationDetailsCalled);
}
Again a mocking framework is best. And I'd vote for those, but sometimes this is an easy introduction to testing for these things before you get heavier into mocking.
Regarding using of Expect() in RhinoMocks. I preffer to use stubs and 'Stub()' or AssertWasCalled() methods as much as possible. Expect() is used in cases when nothing else works.

asp.net mvc How to test controllers correctly

I'm having difficulty testing controllers. Original my controller for testing looked something like this:
SomethingController CreateSomethingController()
{
var somethingData = FakeSomethingData.CreateFakeData();
var fakeRepository = FakeRepository.Create();
var controller = new SomethingController(fakeRepository);
return controller;
}
This works fine for the majority of testing until I got the Request.IsAjaxRequest() part of code. So then I had to mock up the HttpContext and HttpRequestBase. So my code then changed to look like:
public class FakeHttpContext : HttpContextBase
{
bool _isAjaxRequest;
public FakeHttpContext( bool isAjaxRequest = false )
{
_isAjaxRequest = isAjaxRequest;
}
public override HttpRequestBase Request
{
get
{
string ajaxRequestHeader = "";
if ( _isAjaxRequest )
ajaxRequestHeader = "XMLHttpRequest";
var request = new Mock<HttpRequestBase>();
request.SetupGet( x => x.Headers ).Returns( new WebHeaderCollection
{
{"X-Requested-With", ajaxRequestHeader}
} );
request.SetupGet( x => x["X-Requested-With"] ).Returns( ajaxRequestHeader );
return request.Object;
}
}
private IPrincipal _user;
public override IPrincipal User
{
get
{
if ( _user == null )
{
_user = new FakePrincipal();
}
return _user;
}
set
{
_user = value;
}
}
}
SomethingController CreateSomethingController()
{
var somethingData = FakeSomethingData.CreateFakeData();
var fakeRepository = FakeRepository.Create();
var controller = new SomethingController(fakeRepository);
ControllerContext controllerContext = new ControllerContext( new FakeHttpContext( isAjaxRequest ), new RouteData(), controller );
controller.ControllerContext = controllerContext;
return controller;
}
Now its got to that stage in my controller where I call Url.Route and Url is null. So it looks like I need to start mocking up routes for my controller.
I seem to be spending more time googling on how to fake/mock objects and then debugging to make sure my fakes are correct than actual writing the test code. Is there an easier way in to test a controller? I've looked at the TestControllerBuilder from MvcContrib which helps with some of the issues but doesn't seem to do everything. Is there anything else available that will do the job and will let me concentrate on writing the tests rather than writing mocks?
Thanks
You can use some of the libraries that give you out of the box some of these objects. For example RhinoMock, NMock ... etc. I personally use Moq - it's good enough and free. What i like most in Moq is the linq expressions.
Most mocking engine will do all this for you. I use RhinoMocks but there are a lot more available. Also Moles is very new and interesting mocking engine (this generally comes with Pex which is yet more ammo in your unit testing arsenal)
MvcContrib + RhinoMocks. Check out the TestControllerBuilder in the MvcContrib.TestHelper library. Here's the official write-up: http://mvccontrib.codeplex.com/wikipage?title=TestHelper#Examples.
Here's an example of mocking a controller out for testing a UrlHelper: ASP.NET MVC: Mock controller.Url.Action
Here's a short explanation of how to use the TestControllerBuilder: http://codebetter.com/blogs/kyle.baley/archive/2008/03/19/testcontrollerbuilder-in-mvccontrib.aspx
Instead of mocking stuff, you can pass IAjaxRequest to constructor. Or make it base constructor class property (and use property injection). Or you can make your constructor implement IAjaxRequest and then apply global action filter on base constructor class that will setup IAjaxRequest.
This will help to abstract many things, including HttpContext stuff. Just don't abstract IHttpContext, abstract IUserContext, ISessionStorage, IAuthentication, IRequestDetails...
Another way is to use model binder directly on methods where you need specific information. See this post for example. You can make binder that will give you IsAjaxRequest, then you just make action to accept this parameter. Works very well because information is provided exactly to the method that needs it, not to the whole controller.

Testing the User.IsInRole in MVC.NET

I am trying to test the User.IsInRole("Administrator") in my application, and actually trying to assign the User Role to ("Administrator") so that my test will pass. I am using Scott Hanselman's MvcMockHelpers to do this, and at the moment I have the following test.
[Test]
public void Create_CanInsertNewArticleView_IsNotNull()
{
// Arrange
var controller = new ArticleController();
MockRepository mockRepo = new MockRepository();
var fakeContext = MvcMockHelpers.FakeHttpContext(mockRepo, "~/Article/Create");
fakeContext.User.IsInRole("Administrator");
// Act
Article fakeArticle = FakeObjects.ReturnFakeArticle();
var result = controller.Create(fakeArticle) as ViewResult;
// Assert
Assert.IsNotNull(result);
}
However the actual controller's User is null at the moment.
Can anyone help me out and tell me what the correct test should be, to User.IsInRole("Administrator")
Thanks for your help and time
Johann
See this related answer for details.
Here's the code snippet from the other answer converted to Rhino Mocks:
var user = new GenericPrincipal(new GenericIdentity(string.Empty), null);
var httpCtx = MockRepository.GenerateStub<HttpContextBase>();
httpCtx.User = user;
var controllerCtx = new ControllerContext();
controllerCtx.HttpContext = httpCtx;
sut.ControllerContext = controllerCtx;
You'll have to mock an IPrincipal for your user object, set it up so that .IsInRole("Administrator") returns true, and then set your fakeContext up to return that IPrincipal for the.User property. It would be something like this:
EDIT: It turns out the OP is using Rhino Mocks, and the code I provided was for Moq. Here's an attempt att writing Rhino code, although I have never actually used Rhino myself. The original Moq code can be found below.
In Rhino Mocks, you'll want to add another helper method, or change the current one, so you have the following:
public static HttpContextBase FakeHttpContext(this MockRepository mocks, string url, IPrincipal user)
{
// Do the same setup as Scott does...
// ...and add this:
SetupResult.For(context.User).Return(user);
mocks.Replay(context);
return context,
}
Then you declare and set up your IPrincipal mock object like this before the call to FakeHttpContext, and send the mock object in as the third parameter.
In Moq:
fakeContext = MvcMockHelpers.FakeHttpContext("~/Article/Create");
fakeUser = new Mock<IPrincipal>();
fakeUser.Expect(usr => usr.IsInRole(It.IsAny<String>())).Returns(true);
fakeContext.Expect(context => context.User).Returns(fakeUser.Object);
(Disclaimer: It was a while since I wrote a unit test, and this code has not been tested even for compilation errors. Hence, there might be some wrinkles that need to be ironed out before you can use this code, but you get the general idea...)

Resources