When to specify certain Setups in Moq - asp.net

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();...

Related

Moq.MockVerificationException not public xUnit Assert.Throws

I am testing a method which will call another method if certain parameters are certain values and not if they are other.
I was using Moq's Verify to test this. However when I use the xUnit to see if the method is not called when sending parameters with data which should not make the method call the 2nd method.
Problem is that I cannot do
mockObject.Verify();
Assert.Throws<Moq.MockVerificationException>(()=>mockObject.Method());
I changed from MSTest to xUnit because the support for throws was built in and I had to have the ExpectedException attribute decorating my test method before.
I tried to cast the Moq non-public exception to the public parent Moq.MoqException but that will throw an error.
so I think I may have to do:
try {moqObj.Verify();}
catch(Moq.Exception mve)
{
Assert.SomethingIsException();
}
As I understand, you're just trying to verify whether certain methods are called or not? If so, try this:
var theThing = new Mock<IThing> ();
theThing.Verify (x => x.DoSomething ("a"), Times.Never);
theThing.Verify (x => x.DoSomething ("b"), Times.Once);
If you need to invoke another method after the first method is called, you could use a callback:
theThing.Setup (x => x.DoSomething ("a")).Callback (() => {});

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);

Why register with Unity when instance is already mocked

I just came across some existing code from an existing application and I'm trying to understand the first two lines in the unit test. Here is the unit test:
[TestMethod]
public void CanDisplayReportWithPage()
{
var claimComponent = new Mock<IClaimsComponent>();
GlobalContainer.Unity.RegisterInstance(claimComponent.Object);
_pharmacyCdmService
.Setup(service => service.ReadAllTenantEstablishments((It.IsAny<Guid>())))
.Returns(ResponseHelper.CreateResponse(new TenantEstablishmentDataContract[0]));
_pharmacyCdmService
.Setup(service => service.ReadTenantById((It.IsAny<long>())))
.Returns(ResponseHelper.CreateResponse(new TenantDataContract()));
claimComponent.Setup(
component => component.FileDetailsClaimReport(It.IsAny<RamqDetailsClaimReportRequestDataContract>()))
.Returns(new RamqDetailsClaimReportResponseDataContract());
var result = (ViewResult)_controller.View(new DetailsReportModel(), 3);
_pharmacyCdmService.VerifyAll();
_claimIdentityHelper.VerifyAll();
Assert.IsNotNull(result);
Assert.IsNotNull(result.Model);
Assert.AreEqual("Index", result.ViewName);
Assert.IsInstanceOfType(result.Model, typeof(DetailsReportModel));
Assert.AreEqual(2, ((DetailsReportModel) result.Model).DataContract.PageTransaction);
}
This test uses a combination of Moq and Unity. What I'm trying to understand is why the mocked instance (claimComponent) has to be registered with Unity.
My guess is the system under test uses the Service Locator anti-pattern. GlobalContainer is the key - it's probably a Singleton (generally another anti-pattern) that makes the IoC container available everywhere.
A better alternative would be to use constructor injection (probably with the controller) using Unity.MVC3 or equivalent. That lets you compose everything in one Composition Root. Your unit tests typically don't need to reference Unity at all; they can just create a mock and pass it to the controller.

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());

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

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.

Resources