ASP.NET MVC - Unit testing, mocking HttpContext without using any mock framework - asp.net

Since I'm having problem with unit testing RenderPartialViewToString() with Moq framework (ASP.NET MVC - Unit testing RenderPartialViewToString() with Moq framework?), I'm thinking about getting my controller directly, without using Moq for these particular test, however, how do I mocks (or set) the HttpContext for my test without using any Moq framework?
I need to able to do something similar to this, without Moq of course:
var mockHttpContext = new Mock<ControllerContext>();
mockHttpContext.SetupGet(p => p.HttpContext.User.Identity.Name).Returns("n1\\test");
mockHttpContext.SetupGet(p => p.HttpContext.Request.IsAuthenticated).Returns(true);
Thank you very much.

If your controller need authentication info from HttpContext, I would:
Create a new class that wraps the calls you care about. Looks like you want Name and IsAuthenticated. The new class can be AuthenticationService or something.
In the methods/properties in AuthenticationService, call into the real HttpContext, like HttpContext.Current.user.Identity.Name.
Create an interface over the new
AuthenticationService with the
public methods/properties you care about.
Inject the IAuthenticationService
into your controller under test in
the constructor. Looks like you may already be doing that with other dependencies in the controller.
Now you can mock
IAuthenticationService and it's
return values without needing to
call into the real HttpContext.
Here are more details from a blog post I did http://www.volaresystems.com/Blog/post/2010/08/19/Dont-mock-HttpContext.aspx. I'm using RhinoMocks instead of Moq, but the concept is the same for staying away from HttpContext.

You can mock it as follows and declare a stringBuilder object that accepts the output.
var response = new Mock<HttpResponseBase>();
response.Setup(x => x.Write(It.IsAny<string>())).Callback<string>(y => _stringBuilder.Append(y));
var url = new Uri("http://localhost/Home/");
var request = new Mock<HttpRequestBase>();
request.Setup(x => x.Url).Returns(url);
request.Setup(x => x.ApplicationPath).Returns("");
var httpContext = new Mock<HttpContextBase>();
httpContext.Setup(x => x.Request).Returns(request.Object);
httpContext.Setup(x => x.Response).Returns(response.Object);
_controllerContext = new Mock<ControllerContext>();
_controllerContext.Setup(x => x.HttpContext).Returns(httpContext.Object);
_homeController = autoMock.Create<HomeController>();
_homeController.ControllerContext = _controllerContext.Object;
You execute your action as follows:
var action=_homeController.Action(<parameters>);
action.ExecuteResult();
and now your stringbuilder object i.e _stringBuilder will have the result output whatever type it is and you can test it.

Related

How to mange API endpoints?

Configured the HttpClient in the startup.cs.
services.AddHttpClient("jsonPosts", client => {
client.BaseAddress = new Uri("https://jsonplaceholder.typicode.com/");
On the Controller calling API:
// Obtaining _clientFactory by DI on the Controller constructor
var client = _clientFactory.CreateClient("jsonPosts");
var myContent = JsonConvert.SerializeObject(myObjectToSerialize);
HttpContent stringContent = new StringContent(myContent, Encoding.UTF8, "application/json");
HttpResponseMessage result = await client
.PostAsync(client.BaseAddress + "posts/1", stringContent)
.ConfigureAwait(false);
You can can see on the PostAsync method the API endpoint is being appended to the base address of the HttpClient.
Is this the recommended approach of managing different endpoints across an application?
Well, that depends on your application.
If you only have to do few things like authenticate, post something, exit application then there´s no reason to do the work and create a structure thatfor.
If you do multiple calls and especially want to do the same call at different points in your code you should create an api wrapper.
A common way is to create one generic method that takes an Type as generic argument, also give it the url, HTTP method and other data you might need.
The method will do the call with the arguments given, automatically Deserialize the JSON to an Object of the generic type and return it to you.
This way you can do something like this with only having to write one method and define classes for the Results. You might even use dynamics without defining classes but I personally don´t like dynamics.
ApiClient api = new ApiClient(baseUrl);
User user = api.get<User>("/user", new Query().add("user", "admin"));
EmailList emails = api.get<EmailList>("/user/emails");
Then you could still populate it into multiple methods if you don´t want to mess with the endpoints like
public User getUser(String username){
User user = api.get<User>("/user", new Query().add("user", "admin"));
return user;
}
And use it like
MyApiWrapper.getUser("admin");

When to specify certain Setups in Moq

I'm trying to follow this Get Started example for testing with Moq. I'm able to duplicate the examples within my own testing project and can get my tests to pass (testing my service where my context is injected). However, what I don't understand is WHEN to use each of the following Setup calls:
var mockSet = new Mock<DbSet<Blog>>();
mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<Blog>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<Blog>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<Blog>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
Can someone explain in very basic terms as to when each of these should be used?
For example, It seems that if the method in my service that I'm testing uses an expression, I need to do the 2nd setup call above (I've done some trial and error by removing and re-inserting these calls). I've been to the Moq documentation as well as MSDN for Table-TEntity and I still don't see it. Perhaps because I don't have a strong grasp of the Linq namespace.
TL;DR - When using an Entity Framework DBContext dependency, you will need perform these Setups on any DBSet which you intend to mock, specifically to return fake data to any LINQ queries on the DBSet. All 4 setups should be done for each mocked DbSet - this can be done generically in a helper method.
In more Detail:
In general, with Strict mode off, Setup is only required on methods that you actually want to Mock. In this case, if you haven't done a Setup on a method which is invoked during your Unit Test, Moq will instead provide default behaviour for any method which hasn't been explicitly Setup, which typically is to return the default(T) of any expected return type, T. For classes, the default is null, which isn't really going to help any during testing of classes dependent on a Mocked EF DbContext.
The specific example you have provided is the standard mocked setup for an Entity Framework DbSet, which then allows you to provide fake data for this specific DbSet (DbSet<Blog>), by providing an alternative IQueryable<Blog> from a List<Blog> collection (as opposed to the usual concrete RDBMS implementation).
A suggestion would be to move the DbSetmock code into your standard unit test plumbing setup framework / toolkit, to create a helper method like:
public static Mock<IDbSet<T>> GetMockedDbSet<T>(IList<T> fakeData) where T : class, new()
{
var data = fakeData.AsQueryable();
var mockSet = new Mock<IDbSet<T>>();
mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(data.Provider);
mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(data.Expression);
mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(data.ElementType);
mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
return mockSet;
}
Which you can then set up on your Mock DBContext, as follows:
var mockContext = new Mock<IMyDbContext>();
var mockBlogDbSet = GetMockedDbSet<Blog>(new List<Blog>{... fake data here ...});
mockContext.Setup(c => c.Blogs).Returns(mockBlogDbSet.Object);
var sut = new SomeClassIWantToTest(mockContext.Object); // Inject dependency into Ctor
sut.DoSomething();...

how to hide metadata in web api 2, odata

I have defined odata route using MapODataServiceRoute in my WebApiConfig.
config.Routes.MapODataServiceRoute("CompanyoOdata", "odata", GetImplicitEdm(config));
private static IEdmModel GetImplicitEdm(HttpConfiguration config)
{
ODataModelBuilder builder = new ODataConventionModelBuilder(config, true);
builder.EntitySet<Company>("Company");
builder.EntitySet<Photo>("Photos");
builder.EntitySet<Country>("Country");
return builder.GetEdmModel();
}
The data service works just fine. But I want to achieve few things.
I don't want to expose my metadata or associations because i'm using it internally and will not need metadata. How can I restrict access to these information (i.e restrict access to http://www.sample.com/odata/#metadata or http://www.sample.com/odata/$metadata)
secondly, I want to ignore some properties from getting serialized. I found two ways of doing this.
Using data contracts and marking properties with [DataMember] attribute or [IgnoreDataMember] attribute
Using Ignore method on EntitySet when building the model
I can't use the first method as I'm using Database first approach for entity framework hence can't decorate the entity with attributes. I thought I can achieve this by using MetaDataType, but it seems it only works for DataAnnotations.
I used second method with success, but you can't pass more than one property in the ignore method. Has to do it to individual property that I need to ignore, which is a bit tedious. Is there another way to do this?
any help really appreciated.
If want to hide metadata (/$metadata) or service document (/), can remove the the MetadataRoutingConvention from existing routing conventions, e.g.:
var defaultConventions = ODataRoutingConventions.CreateDefault();
var conventions = defaultConventions.Except(
defaultConventions.OfType<MetadataRoutingConvention>());
var route = config.MapODataServiceRoute(
"odata",
"odata",
model,
pathHandler: new DefaultODataPathHandler(),
routingConventions: conventions);
If only expose a few properties per type, can use ODataModelBuilder instead of ODataConventionModelBuilder. E.g., some example:
ODataModelBuilder builder = new ODataModelBuilder();
EntityTypeConfiguration<Customer> customer = builder.EntitySet<Customer>("Customers").EntityType;
customer.HasKey(c => c.Id);
customer.Property(c => c.Name);

Is there an equivalent of the Rhino Mocks .Do() method in Moq?

Is there an equivalent of the Rhino Mocks .Do() method in Moq? I am converting my Rhino Mocks code to Moq, and am stuck on the following:
mockedObject
.Expect(x => x.GetSomething())
.Do((Func<SomeClass>)(() => new SomeClass());
This is not the same as (in Moq, similar in Rhino Mocks):
mockedObject
.Setup(x => x.GetSomething())
.Return(new SomeClass());
When GetSomething() is called multiple times in your unit test, the first piece of code will always return a new instance. The second piece will always return the same instance.
What I want is for my mocked object (with Moq) to always return a new instance. So I actually want to provide an implementation of the GetSomething() method to my mocked object.
Using sequences won't do the trick, because I don't know how many times GetSomething() will be called, nor am I interested in this.
You should be able to pass .Returns a Func<SomeClass> just like you're doing with Rhino mocks:
mockedObject
.Setup(x => x.GetSomething())
.Returns(() => new SomeClass());

Moq caches return value

Seems like Moq is caching data I set up as return. When I do this:
var service = new Mock<AlbumService>();
service.Setup(x => x.CreateOne()).Returns(new AlbumService().CreateOne());
it returns the same object even thought AlbumService.CreateOne() returns new Album instance.
Is it possible to make Moq call the Returns Action every time I access CreateOne() ?
This ought to help:
var service = new Mock<AlbumService>();
service.Setup(x => x.CreateOne()).Returns(() => new AlbumService().CreateOne());
To elaborate, the Returns method accepts an object of the return type or a delegate that will evaluate to the return type. The delegate is invoked whenever the mocked method is invoked.

Resources