How to mock up a static method in a static class with URLHelp? (Moq) - model-view-controller

I have a extension method. Can any one help me how to test this method with Moq?
public static string GetBaseUrl(this UrlHelper urlHelper)
{
Uri contextUri = new Uri(urlHelper.RequestContext.HttpContext.Request.Url, urlHelper.RequestContext.HttpContext.Request.RawUrl);
UriBuilder realmUri = new UriBuilder(contextUri) { Path = urlHelper.RequestContext.HttpContext.Request.ApplicationPath, Query = null, Fragment = null };
string url = realmUri.Uri.AbsoluteUri;
if (url.EndsWith("/"))
{
url = url.Remove(url.Length - 1, 1);
}
return url;
}
many thanks.

As TrueWill points out, you can't use Moq directly with UrlHelper.RequestContext because it isn't virtual. On the other hand, UrlHelper is a public class that you can instantiate for use with unit testing.
At some point, however, you will encounter the need to assign a HttpContextBase to create the UrlHelper, and Moq can help you to do that.
Here's a test that shows that I can at least write a unit test that invokes your GetBaseUrl without throwing any exceptions:
[TestMethod]
public void Test1()
{
var httpCtxStub = new Mock<HttpContextBase>();
httpCtxStub.SetupGet(x => x.Request).Returns(() =>
{
var reqStub = new Mock<HttpRequestBase>();
reqStub.SetupGet(r => r.RawUrl).Returns("http://foo");
reqStub.SetupGet(r => r.Url).Returns(new Uri("http://foo"));
return reqStub.Object;
});
var requestCtx = new RequestContext(httpCtxStub.Object, new RouteData());
var urlHelper = new UrlHelper(requestCtx, new RouteCollection());
var result = urlHelper.GetBaseUrl();
// Assert something
}
However, this isn't the simplest unit test to write and maintain, so I support TrueWill's comment that you might make life simpler for yourself if you hide UrlHelper behind an interface.

The UrlHelper.RequestContext property is non-virtual. Moq isn't going to be of help in this case, to the best of my knowledge.
You could create a wrapper class for UrlHelper that implements an interface, but that would seem to defeat the purpose of using an extension method.
Typemock would probably do what you want, if you have the budget for a commercial program. (I haven't tried it; I use Moq myself.)
Another option would be to write integration tests against this method; while they would run more slowly than unit tests, I suspect this method is unlikely to version often.
A larger issue is coupling to UrlHelper reducing testability in the rest of your application. Perhaps other posters can suggest answers to that issue.

Related

Recommended way to test Scheduler/Throttle

I'm in the process of rewriting one little WPF-App I wrote to make use of ReactiveUI, to get a feeling about the library.
I really like it so far!
Now I've stumbled upon the Throttle method and want to use it when applying a filter to a collection.
This is my ViewModel:
namespace ReactiveUIThrottle
{
public class MainViewModel : ReactiveObject
{
private string _filter;
public string Filter { get => _filter; set => this.RaiseAndSetIfChanged(ref _filter, value); }
private readonly ReactiveList<Person> _persons = new ReactiveList<Person>();
private readonly ObservableAsPropertyHelper<IReactiveDerivedList<Person>> _filteredPersons;
public IReactiveDerivedList<Person> Persons => _filteredPersons.Value;
public MainViewModel()
{
Filter = string.Empty;
_persons.AddRange(new[]
{
new Person("Peter"),
new Person("Jane"),
new Person("Jon"),
new Person("Marc"),
new Person("Heinz")
});
var filterPersonsCommand = ReactiveCommand.CreateFromTask<string, IReactiveDerivedList<Person>>(FilterPersons);
this.WhenAnyValue(x => x.Filter)
// to see the problem
.Throttle(TimeSpan.FromMilliseconds(2000), RxApp.MainThreadScheduler)
.InvokeCommand(filterPersonsCommand);
_filteredPersons = filterPersonsCommand.ToProperty(this, vm => vm.Persons, _persons.CreateDerivedCollection(p => p));
}
private async Task<IReactiveDerivedList<Person>> FilterPersons(string filter)
{
await Task.Delay(500); // Lets say this takes some time
return _persons.CreateDerivedCollection(p => p, p => p.Name.Contains(filter));
}
}
}
The filtering itself works like a charm, also the throttling, when using the GUI.
However, I'd like to unittest the behavior of the filtering and this is my first attempt:
[Test]
public void FilterPersonsByName()
{
var sut = new MainViewModel();
sut.Persons.Should().HaveCount(5);
sut.Filter = "J";
sut.Persons.Should().HaveCount(2);
}
This test fails because the collection still has 5 people.
When I get rid of the await Task.Delay(500) in FilterPersons then the test will pass, but takes 2 seconds (from the throttle).
1) Is there a way to have the throttle be instant within the test to speed up the unittest?
2) How would I test the async behavior in my filter?
I'm using ReactiveUI 7.x
Short answers:
Yes, by making sure you're using CurrentThreadScheduler.Instance when running under test
Instead of using CurrentThreadScheduler, use a TestScheduler and manually advance it
The longer answer is that you need to ensure your unit tests can control the scheduler being used by your System Under Test (SUT). By default, you'll generally want to use CurrentThreadScheduler.Instance to make things happen "instantly" without any need to advance the scheduler manually. But when you want to write tests that do validate timing, you use a TestScheduler instead.
If, as you seem to be, you're using RxApp.*Scheduler, take a look at the With extension method, which can be used like this:
(new TestScheduler()).With(sched => {
// write test logic here, and RxApp.*Scheduler will resolve to the chosen TestScheduler
});
I tend to avoid using the RxApp ambient context altogether for the same reason I avoid all ambient contexts: they're shared state and can cause trouble as a consequence. Instead, I inject an IScheduler (or two) into my SUT as a dependency.

Can you record accessed methods in Visual Studio?

I'm retroactively documenting and writing unit tests for some C# code. I would like to determine what code is actually being used and when.
In Visual Studio 2012, is there a way to record all the methods accessed and in what order while walking through specific scenarios?
You could run your application with a profiler attached, which will give you all accessed methods, call chains, counts, etc.
The Visual Studio Profiler will give you the time spent in each method, and let you inspect the call heirarchy. I don't know if it will give you the exact order they were called in though.
EDIT: Apparently attaching the profiler to a running unit test is harder in VS2012.
Are you wanting to execute a test method that make sure that a particular method on a class was invoked ? If so i dont know of a way to do it in VS alone, but you can use a mock framework to create dependency mocks and check values on them. Here is a snippet of a unit test:
[TestMethod]
public void HttpPostPrivacyPolicyFacadeSvcErrorTest()
{
var controller = ControllerHelper.GetRouteController();
controller.Session[SessionVariable.User] = new UserInfo() { UserName = Config.Data.Username };
var idmSvcMock = new Mock<IUserServiceDAO>();
var facadeSvcMock = new Mock<IFacadeSvcDAO>();
//setup the facade mock to throw exception to simulate FacadeServiceException
facadeSvcMock.Setup(x => x.SetPrivacyAcceptanceStatus(It.IsAny<UserInfo>())).Throws<Exception>();
var userCollectorMock = new Mock<IUserInfoCollector>();
userCollectorMock.Setup(x => x.GetUserInfo()).Returns(new UserInfo() { UserName = Config.Data.Username });
controller.FacadeSvc = facadeSvcMock.Object;
controller.UserServiceDAO = idmSvcMock.Object;
controller.UserCollector = userCollectorMock.Object;
controller.DefaultErrorId = "Route_errors_Unabletoprocess";
//action
var res = controller.Privacy(new FormCollection());
//assert
//make sure we go to the right controller, action, with the correct params.
res.AssertActionRedirect().ToController("Errors").ToAction("Index").WithParameter("id", "Route_errors_Unabletoprocess");
//did we call setprivacy once on the mock?
facadeSvcMock.Verify(x => x.SetPrivacyAcceptanceStatus(It.IsAny<UserInfo>()), Times.Exactly(1));
In the test above i check that SetPrivacyAcceptance was invoked once and only once on my facadeSvcMock instance. More on moq here: Moq
this block of code is actually checking how many times SetPrivacyAcceptanceStatus was invoked:
//did we call setprivacy once on the mock?
facadeSvcMock.Verify(x => x.SetPrivacyAcceptanceStatus(It.IsAny()), Times.Exactly(1));
the It.IsAny() is the one parameter to that method, so the line above says basically "For any input parameter of type UserInfo verify that we invoked SetPrivacyAcceptanceStatus exactly once."

Testing controllers using IoC

Im started to learn TDD just now. And i have some troubles with testing my controllers. So, i will try to explain.
I have a controller:
public AccountController(IStoreService storeService)
{
_storeService = storeService;
}
public virtual ActionResult RenderBalance()
{
var model = _storeService.GetStorePageBalanceModel();
return PartialView("MyControl", model);
}
Here i want to test my RenderBalance action:
public class when_balance_renders
{
private static Mock<IStoreService> storeService = new Mock<IStoreService>();
private static AccountController controller;
private static ActionResult result;
private Establish context = () =>
{
controller = new AccountController(storeService.Object);
result = controller.RenderBalance();
};
private It should_be_not_null_result = () => { result.ShouldNotBeNull(); };
}
But this code doesn't work. I have this error on debug mode:
Could not load file or assembly or one of its dependencies. An attempt was made to load a program with an incorrect format.
How may i fix it? And can you give me some recommendations about testing controllers.
Thanks, Nogin Anton.
If you are just starting out with TDD, try a simpler approach like classical TDD as pointed out here http://martinfowler.com/articles/mocksArentStubs.html
Also if you have this error Could not load file or assembly or one of its dependencies. An attempt was made to load a program with an incorrect format.
There is something very basic setup wrong. Remove lines of code until you can at least compile, then move forward from there.

using Moq - void return type method Unit test

I am writing unittest for void method actually that method load the collection in
ViewData["CityList"] method is
public void PopulateCityCombo() {
IEnumerable<Cities> c= service.GetCities();
ViewData["CityList"] = c.Select(e => new Cities{ ID = e.ID, Name = e.Name});
}
now i do not know how to unit test using Moq since controller method is void and not returning data, can any one tell i will achive that.
On a side note, I would shy away from using ViewData within controller methods as per your example. The ViewData dictionary approach is fast and fairly easy to implement, however it can lead to typo's and errors that are not caught at compile time. An alternative would be to use the ViewModel pattern which allows you to use strongly-typed classes for the specific view you need to expose values or content within. Ultimately giving you type safe and compile time checking along with intellisense.
Switching to the ViewModel pattern would allow you to call the PopulateCityCombo() method from your controller to populate a ViewModel that in turn would passed to the corresponding view.
From there you would need to inject a mock service layer into your controllers constructor from your unit test.
// arrange
var mock = new Mock<servicelayer>();
mock.Setup(x=>x.GetCities()).Returns(expectedData);
var controller = new YourController(mock.Object);
// act
var result = controller.ControllerMethod() as ViewResult;
var resultData = (YourViewModel)result.ViewData.Model;
// assert
// Your assertions

TDD, Mocking, dependency injection and the DRY principle

I've got a controller class which accpets multiple parameters in the ctor which gets injected at runtime.
Example:
public ProductController(IProductRepositort productRepository,
IShippingService shippingService, IEmailProvider emailProvider)
{
...
}
I am finding that the Test methods are getting huge. I am setting up the methods as follows:
[Test]
public void CanSendProduct()
{
//Code to set up stub
List<Product> products = new List<Product>();
for (int i = 0; i < length; i++)
{
products.Add(new Product()));
}
var mockProductRepository = new Mock<IProductRepository>();
mockProductRepository.Setup(x => x.GetProducts()).Returns(products);
//Code to set up stub
....
....
var mockShippingService = new Mock<IShippingService>();
mockShippingService.Setup(x => x.GetShippers()).Returns(shippers);
//Code to set up stub
.....
.....
var mockEmailProvider = new Mock<IEmailProvider>();
mockEmailProvider.Setup(x => x.Send()).Returns(provider);
//Execute Test
....
....
//Assert
....
....
}
Obviously, it not practical to repeat the mock setup in every method of this test class.
How can i create rich mocking objects that enables me to do Behavioural verification of my tests and at the same time minimise the setup pain?
What are the TDD best practices to deal with this problem?
Thanks
If your test framework supports setup/teardown functions that will be called before and after each test, create and destroy some "default" mock objects in those functions. Your tests can simply use those, and for special cases where the default mock objects don't work for you, you can simply ignore them and create local mock objects within those tests.
Use a Behavioural, or functional testing suite. Looks like your in C# or Java? Either way I would recommend FItnesse but there are others. As for the unit tests, I would probably use a IOC container like Winsor/Castle or Spring, then you can set up a container for the tests thats filled with Mocks rather than "real" objects.
I'd just extract this code into methods (if your mock framework requires you to pass the mock factory in, change the signature as needed):
private Mock<IProductRepository> SetupStandardMockProductRepository() {
List<Product> products = new List<Product>();
for (int i = 0; i < length; i++) {
products.Add(new Product()));
}
var mockProductRepository = new Mock<IProductRepository>();
mockProductRepository.Setup(x => x.GetProducts()).Returns(products);
}
// ... and so forth
Then, in your tests:
var mockProductRepository = SetupStandardMockProductRepository();
// or make these static properties of some central test class, like this:
var mockProductRepository = Stubs.StandardProductRepository;

Resources