MVC moq with repository that uses lambda expression - asp.net-mvc-3

I have a controller method that acceses a repository method which has lambda expression as parameter:
// GET: /Product/
public ViewResult List(string category, int page = 1) {
ProductsListViewModel productsListViewModel = new ProductsListViewModel {
Products = _repository.GetByPage(q => q.Category == category || category == null, page, PageSize),
PagingInfo = new PagingInfo {
CurrentPage = page,
ItemsPerPage = PageSize,
TotalItems = _repository.Get(q=>q.Category==category || category==null).Count()
},
CurrentCategory = category
};
return View(productsListViewModel);
}
In my unit test, when controller invokes the repository method, returned object("result" variable) is always null, do you have any idea about this situation?
public void Can_Paginate() {
//Arrange
//Create mock repository
Mock<IProductRepository> mock = new Mock<IProductRepository>();
mock.Setup(q => q.GetByPage(c=>c.Category=="C1",1,3)).Returns(new List<Product>
{
new Product {Id = 1, Name = "P1", Category = "C1"},
new Product {Id = 2, Name = "P2", Category = "C1"},
new Product {Id = 3, Name = "P3", Category = "C1"}
});
mock.Setup(q => q.Get(c => c.Category == "C1")).Returns(new List<Product>
{
new Product {Id = 1, Name = "P1", Category = "C1"},
new Product {Id = 2, Name = "P2", Category = "C1"},
new Product {Id = 3, Name = "P3", Category = "C1"}
});
//Create a controller and make page size 3 items
ProductController controller = new ProductController(mock.Object);
controller.PageSize = 3;
//Action
ProductsListViewModel result = (ProductsListViewModel) controller.List("C1", 1).Model;
//Assert
Assert.IsTrue(result.Products.Count()==3);
}
Thanks

Just had quick look at the moq wiki and it had an example of matching Func<int>
as a parameter. So to match an argument of Func<string> you would write something like this:
mock.Setup(q => q.GetByPage(It.Is<string>(c=>c.Category=="C1"),1,3)).Returns...

Related

asp.net core3 error: not all code paths return a value

I have two tables with similar data for body insurance and third party car insurance ... I have used enum in the model to separate the insurances and I want to do the creation operation for it .... There are two modes for each insurance. One case when that car does not have insurance yet and the second case when we want to extend it.
I wrote this code to create the form, but it encounters the following error
I also get an error on the name of the Create function.error = not all code paths return a value.
Please advise
public async Task<IActionResult> Create(int id, int type)
{
InsuranceViewModel model;
ViewBag.Type = type;
var companies = await _context.InsuranceCompany
.Where(e => e.IsActice)
.ToListAsync();
ViewData["CompanyList"] = new SelectList(companies, "Id", "CompanyName");
if ((InsuranceType)type == InsuranceType.Body)
{
var bodyInsurance = await _context.BodyInsurance
.Include(e => e.InsuranceCompany)
.FirstOrDefaultAsync(e => e.Id == id);
if (bodyInsurance == null)
{
model = new InsuranceViewModel
{
CompanyId = bodyInsurance.InsuranceCompanyId,
CompanyName = bodyInsurance.InsuranceCompany.CompanyName,
InsuranceType = InsuranceType.Body,
IssueDate = new DateTime(bodyInsurance.IssueDate).Ticks,
ExpireDate = new DateTime(bodyInsurance.ExpireDate).Ticks,
VehicleInformationId = id
};
}
else
{
var lastBody = await _context.BodyInsurance.Include(e => e.InsuranceCompany)
.Where(e => e.VehicleInformationId == id)
.OrderBy(e => e.ExpireDate)
.LastAsync();
model = new InsuranceViewModel
{
ExpireDate = new DateTime(lastBody.ExpireDate).AddYears(1).AddDays(1).Ticks,
CompanyId = lastBody.InsuranceCompanyId,
CompanyName = lastBody.InsuranceCompany.CompanyName,
InsuranceType = InsuranceType.Body,
IssueDate = new DateTime(lastBody.ExpireDate).AddDays(1).Ticks,
VehicleInformationId = id
};
}
}
else
{
if ((InsuranceType)type == InsuranceType.Thirdpart)
{
var thirdParty = await _context.ThirdPartyInsurance
.Include(e => e.InsuranceCompany)
.FirstOrDefaultAsync(e => e.Id == id);
if (thirdParty == null)
{
model = new InsuranceViewModel
{
CompanyId = thirdParty.InsuranceCompanyId,
CompanyName = thirdParty.InsuranceCompany.CompanyName,
InsuranceType = InsuranceType.Body,
IssueDate = new DateTime(thirdParty.IssueDate).Ticks,
ExpireDate = new DateTime(thirdParty.ExpireDate).Ticks,
VehicleInformationId = id
};
}
else
{
var lastThirdParty = await _context.ThirdPartyInsurance.Include(e => e.InsuranceCompany)
.Where(e => e.VehicleInformationId == id)
.OrderBy(e => e.ExpireDate)
.LastAsync();
model = new InsuranceViewModel
{
ExpireDate = new DateTime(lastThirdParty.ExpireDate).AddYears(1).AddDays(1).Ticks,
CompanyId = lastThirdParty.InsuranceCompanyId,
CompanyName = lastThirdParty.InsuranceCompany.CompanyName,
InsuranceType = InsuranceType.Body,
IssueDate = new DateTime(lastThirdParty.ExpireDate).AddDays(1).Ticks,
VehicleInformationId = id
};
}
}
return View(model);
}

When I run this method it hits the RedirectToAction but not the breakpoint i have placed above it

I have a class for a cart in a store and when the buy method gets run it skips the breakpoint and still hits the RedirectToAction at the bottom of the method. This is the code for the method
public ActionResult Buy(int productid /*string optionid*/)
{
Product productModel = new Product();
List<ProductOptionJoin> productOptionJoins = GetProductOptions();
var test = productOptionJoins.Where(x => x.ProductID == productid && x.OptionID.ToString() == "1" /*optionid*/).Select(x => new CartItem() { getProduct = x.GetProduct, getOption = x.GetOption });
var i = test;
if (Session["cart"] == null)
{
List<CartItem> cart = new List<CartItem>();
//cart.Add(new CartItem { getProduct = productModel.find(id), getOption = productModel.find(id), Quantity = 1 });
Session["cart"] = cart;
}
else
{
List<CartItem> cart = (List<CartItem>)Session["cart"];
int index = isExist(productid);
if (index != -1)
{
cart[index].Quantity++;
}
else
{
//cart.Add(new CartItem { getProduct = productModel.find(id), getOption = productModel.find(id), Quantity = productModel.find(id) });
}
Session["cart"] = cart;
}
return RedirectToAction("Index");
}
Any ideas?
You are only creating the session variable at the end, maybe put it above?
Product productModel = new Product();
List<ProductOptionJoin> productOptionJoins = GetProductOptions();
var test = productOptionJoins.Where(x => x.ProductID == productid && x.OptionID.ToString() == "1" /*optionid*/).Select(x => new CartItem() { getProduct = x.GetProduct, getOption = x.GetOption });
var i = test;
Session["cart"] = xyz;

LINQ - Group By child property

I have a list of users, each user has string array property called Tags. I am trying to get a unique list of tags and a total count, any idea what I a missing here? I am using LinqPad to write my test query, please see the example code:
void Main()
{
List<User> users = new List<User>(){
new User {Id = 1, Tags = new string[]{"tag1", "tag2"}},
new User {Id = 2, Tags = new string[]{"tag3", "tag7"}},
new User {Id = 3, Tags = new string[]{"tag7", "tag8"}},
new User {Id = 4, Tags = new string[]{"tag1", "tag4"}},
new User {Id = 5 },
};
var uniqueTags = users.Where(m=>m.Tags != null).GroupBy(m=>m.Tags).Select(m=> new{TagName = m.Key, Count = m.Count()});
uniqueTags.Dump();
// RESULT should BE:
// tag1 - Count(2)
// tag2 - Count(1)
// tag3 - Count(1)
// tag4 - Count(1)
// tag7 - Count(2)
// tag8 - Count(1)
}
public class User{
public int Id {get;set;}
public string[] Tags {get;set;}
}
You can flatten to IEnumerable<string> before grouping:
var uniqueTags = users.SelectMany(u => u.Tags ?? new string[0])
.GroupBy(t => t)
.Select(g => new { TagName = g.Key, Count = g.Count() } );
LINQPad C# Expression version:
new[] {
new { Id = 1, Tags = new[] { "tag1", "tag2" } },
new { Id = 2, Tags = new[] { "tag3", "tag7" } },
new { Id = 3, Tags = new[] { "tag7", "tag8" } },
new { Id = 4, Tags = new[] { "tag1", "tag4" } },
new { Id = 5, Tags = (string[])null }
}
.SelectMany(u => u.Tags ?? Enumerable.Empty<string>())
.GroupBy(t => t)
.Select(g => new { TagName = g.Key, Count = g.Count() } )

Combine properties values from a custom List with LINQ

Lets assume I have a list of Persons, in the List I have the following objects:
Person = { ID= 1, State="CA"}
Person = { ID= 2, State="PA"}
Person = { ID= 1, State="NY"}
Person = { ID= 1, State="OH"}
Person = { ID= 3, State="FL"}
Person = { ID= 2, State="KC"}
How do I get a new List Where I can have new Persons by ID only once and if repeated get the State value and put it in the new Person object separated by comma. For example the new List will be
Person = { ID= 1, State="CA,NY,OH"}
Person = { ID= 2, State="PA,KC"}
Person = { ID= 3, State="FL"}
Is there a way to achieve this?
Use Enumerable.GroupBy and String.Join:
var result = persons.GroupBy(p => p.ID)
.Select(g => new Person{
ID = g.Key,
State = string.Join(",", g.Select(p => p.State))
}).ToList();
here is the extension method version
var persons = Person.GroupBy(p => p.ID).Select(p => new Person() { ID = p.Key, State = String.Join(",", p.Select(p2 => p2.State).ToArray()) }).ToList();

Entity Framework, Generic Repositories, and Unit Testing

I solved my problem, but am not sure why things are working and am asking because I always want to know why things work the way they do.
Ok, I am developing an MVC 3 application am utilizing a generic repository, unity for DI, and moq for unit testing. In my unit test for editing an item, my controller initially had this as follows:
AnEntity obj = _anEntityService.GetById(id);
however, when my unit test was calling the Edit(1) in the controller, null was being returned. When I changed the read to be
AnEntity obj = _anEntityService.GetAll().FirstOrDefault(p => p.Id == id);
it returned the mocked item correctly.
Now, I am glad I figured it out, however, I am still scratching my head as to why that worked for unit testing, but the GetById was working as I was running the application.
Any insight would be most helpfull.
Thanks in advance.
Here is the mocked data:
public class AdministrationMockData
{
#region Administration Mock Data
#region County Mock Data
public static void CreateCounty(ref Mock<ICountyService> mock)
{
mock.Setup(m => m.GetAll()).Returns(new List<County>
{
new County { Id = 1, Name = "Adams", StateId = 39, IsActive = true, LastChangedDate = DateTime.Now, LastChangedBy = "dba", AddedDate = DateTime.Now, AddedBy = "dba" },
new County { Id = 2, Name = "Berks", StateId = 39, IsActive = true, LastChangedDate = DateTime.Now, LastChangedBy = "dba", AddedDate = DateTime.Now, AddedBy = "dba" },
new County { Id = 3, Name = "Chester", StateId = 39, IsActive = true, LastChangedDate = DateTime.Now, LastChangedBy = "dba", AddedDate = DateTime.Now, AddedBy = "dba" },
new County { Id = 4, Name = "York", StateId = 39, IsActive = true, LastChangedDate = DateTime.Now, LastChangedBy = "dba", AddedDate = DateTime.Now, AddedBy = "dba" },
new County { Id = 5, Name = "Baltimore", StateId = 21, IsActive = true, LastChangedDate = DateTime.Now, LastChangedBy = "dba", AddedDate = DateTime.Now, AddedBy = "dba" },
new County { Id = 6, Name = "Montgomery", StateId = 21, IsActive = true, LastChangedDate = DateTime.Now, LastChangedBy = "dba", AddedDate = DateTime.Now, AddedBy = "dba" }
}.AsQueryable());
}
#endregion County Mock Data
#region State Mock Data
public static void CreateState(ref Mock<IStateService> mock)
{
mock.Setup(m => m.GetAll()).Returns(new List<State>
{
new State { Id = 21, Name = "Maryland", Code = "MD", IsActive = true, LastChangedDate = DateTime.Now, LastChangedBy = "dba", AddedDate = DateTime.Now, AddedBy = "dba" },
new State { Id = 39, Name = "Pennsylvania", Code = "PA", IsActive = true, LastChangedDate = DateTime.Now, LastChangedBy = "dba", AddedDate = DateTime.Now, AddedBy = "dba" }
}.AsQueryable());
}
#endregion State Mock Data
#endregion Administration Mock Data
}
Here is the Unit Test for Edit
[TestMethod]
public void Can_Edit_County()
{
// Arrange
// - create the mock repositories
Mock<ICountyService> mockCounty = new Mock<ICountyService>();
Mock<IStateService> mockState = new Mock<IStateService>();
AdministrationMockData.CreateCounty(ref mockCounty);
AdministrationMockData.CreateState(ref mockState);
// Arrange
// - create a controller and make the page size 6 items
CountyController controller = new CountyController(mockCounty.Object, mockState.Object);
controller.PageSize = 6;
controller.Testing = true;
// Act
County c1 = controller.Edit(1).ViewData.Model as County;
County c2 = controller.Edit(2).ViewData.Model as County;
County c3 = controller.Edit(3).ViewData.Model as County;
// Assert
Assert.AreEqual(1, c1.Id);
Assert.AreEqual(2, c2.Id);
Assert.AreEqual(3, c3.Id);
}
Here is the controller edit routine:
public ViewResult Edit(int id)
{
//County obj = _countyService.GetById(id);
County obj = _countyService.GetAll().FirstOrDefault(p => p.Id == id);
if (!Testing)
{
PopulateCountyDropDownLists(obj.StateId);
}
return View(obj);
}
I have a generic repository and interface repository which is instantiated by TEntity for each specific entity and also have a service and interface service to execute the repositories. My repository and service is based on: http://efmvc.codeplex.com/releases/view/58663
You get null because you never setup your CountyService to return proper data when calling GetById. Add the below code for setting up the mock and you'll be good to go with the GetById method:
mock.Setup(m => m.GetById(1).Returns(new State { Id = 1, ... });
or set it up to work with any argument passed to the mothod:
mock.Setup(m => m.GetById(It.IsAny<int>()).Returns(new State { ... });

Resources