for unit-testing my asp.net MVC web application, I'd like to mock my IGenericRepository (I'm using Moq).
The method that has to be mocked looks like this:
IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null,
Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, string includeProperties = "");
I've already mocked the repository without any problems:
useraccountRepository = new Mock<IGenericRepository<Useraccount>>();
Now I'd like to tell Moq that when the Get method of my interface is called, a list of useraccounts should be returned:
useraccountRepository.Setup(r => r.Get(u => u.Email == useraccount.Email && u.Password == useraccount.Password)).Returns(useraccounts);
I think there is a mistake in my second lambda because this one works:
useraccountRepository.Setup(r => r.Get(null, null, "")).Returns(useraccounts);
But where's my error?
What also works:
useraccountRepository.Setup(r => r.Get(u => u.Email == useraccount.Email
&& u.Password == useraccount.Password, null, "")).Returns(useraccounts);
It looks like the default parameter values don't apply in my mock. Why is that?
If I use
useraccountRepository.Setup(r => r.Get(u => u.Email == useraccount.Email
&& u.Password == useraccount.Password, null, "")).Returns(useraccounts);
anyway, then the method in my controller throws an exception when the Get message is called:
private bool validateUser(Useraccount useraccount)
{
try
{
Useraccount useraccountLogin = UnitOfWork.UseraccountRepository.Get(
u => u.Email == useraccount.Email && u.Password == useraccount.Password).Single<Useraccount>();
return (useraccountLogin != null);
}
catch (Exception exc)
{
return false;
}
}
Where are my mistakes?
Thank you in advance.
Michael
According to this question Moq.Mock<T> - how to setup a method that takes an expression, setting constraints on expression parameters is unsupported by Moq.
Related
Working with LINQ for the first time in a while and trying to clean something up. I have the following statements:
var element = await _Entities.References
.Where(db => db.LoadId == request.LoadId && db.ReferenceCode == "123")
.OrderByDescending(rec => rec.Created).FirstOrDefaultAsync(cancellationToken);
if (element != null) {
dto.ElementValue = element.Value;
}
I'd like to condense this into a single statement if possible but I was having trouble getting just the value from the await method.
You could do something like this:
dto.ElementValue = (await _Entity.References
.Where(db => db.LoadId == request.LoadId && db.ReferenceCode == "123")
.OrderByDescending(rec => rec.Created)
.FirstOrDefaultAsync(cancellationToken))?.Value
?? dto.ElementValue;
Note that technically this changes the behaviour of the code. Previously, if the query doesn't return a result, the ElementValue property is not touched. With a one-liner, if the query doesn't return a result, the ElementValue getter and setter will both be called.
Also, if the query returns a result whose Value is null, the ElementValue property will be set to itself rather than null.
The HTML Source is as follows
<img id="itemImage" src="https://www.xyz.com/item1.jpg">
I am using the following LINQ query to get the SRC value (Image Link)
string imageURL = document.DocumentNode.Descendants("img")
.Where(node => node.Attributes["id"] != null && node.Attributes["id"].Value == "itemImage")
.Select(node => node.Attributes["src"].Value).ToString();
But the imageURL gives output as
System.Linq.Enumerable+WhereSelectEnumerableIterator`2[HtmlAgilityPack.HtmlNode,System.String]
The problem is casting it to string. Select() returns IEnumerable<T> so you are basically converting an enumerator to a string (as the error message says). Call First() or Single() or Take(1) in order to get a single element before casting it to a string.
.Select(node => node.Attributes["src"].Value).First().ToString();
Also, if there is a chance that the desired element is not present, FirstOrDefault() and SingleOrDefault() returns null rather then throwing an exception. In that case, I would recommend
var imageUlr = ... .Select(node => node.Attributes["src"].Value).FirstOrDefault();
if (imageUrl != null)
{
// cast it to string and do something with it
}
Add .DefaultIfEmpty(string.Empty)
.FirstOrDefault
string imageURL = document.DocumentNode.Descendants("img")
.Where(node => node.Attributes["id"] != null && node.Attributes["id"].Value == "itemImage")
.Select(node => node.Attributes["src"].Value)
.DefaultIfEmpty(string.Empty)
.FirstOrDefault()
.ToString();
Try adding FirstOrDefault():
string imageURL = document.DocumentNode.Descendants("img")
.Where(node => node.Attributes["id"] != null && node.Attributes["id"].Value == "itemImage")
.Select(node => node.Attributes["src"].Value)
.FirstOrDefault();
I have method which accept expression for Linq Where clause. Sometimes I would like to ignore Where clause and do not use it.
I have tried to pass null to the method like this
GetUsersView(null)
but got exception. How correctly do this?
private IQueryable<UserView> GetUsersView(Expression<Func<User, bool>> expression)
{
return _userRepository.GetAll().
Where(expression).
Select(p => new UserView
{
Id = p.Id,
Active = p.Orders.Any(c => c.Active && (c.TransactionType == TransactionType.Order || c.TransactionType == TransactionType.Subscription)),
DateStamp = p.DateStamp,
Email = p.Email,
FirstName = p.FirstName,
LastName = p.LastName,
Message = p.Message,
UsersManager = p.Orders.Select(o => o.Product).Any(w => w.UsersManager && w.Active)
});
}
Passing nulls to methods is a horrible idea. Passing u => true is not very readable either. Create two methods instead - one which has parameter, and other, which don't have. Also I see your method have two responsibilities - it filters users, and converts them to UserViews. I think filtering users by predicate should occur in repository.
You can also create extension method IQueryable<UserView> ToViews(this IQueryable<User> source).
public static IQueryable<UserView> ToViews(this IQueryable<User> source)
{
return source.Select(u => new UserView
{
Id = u.Id,
Active = u.Orders.Any(o => o.Active &&
(o.TransactionType == TransactionType.Order ||
o.TransactionType == TransactionType.Subscription)),
DateStamp = u.DateStamp,
Email = u.Email,
FirstName = u.FirstName,
LastName = u.LastName,
Message = u.Message,
UsersManager = u.Orders.Select(o => o.Product)
.Any(p => p.UsersManager && p.Active)
});
}
In this case code will look like:
private IQueryable<UserView> GetUserViews()
{
return _userRepository.GetAll().ToViews();
}
private IQueryable<UserView> GetUserViews(Expression<Func<User, bool>> predicate)
{
// move filtering to repository
return _userRepository.GetAll(predicate).ToViews();
}
Try using
GetUsersView(u=>true);
or if you would prefer not to type the expression all the time, you can create an overloaded function that provides a default expression.
IQueryable<UserView> GetUsersView()
{
return GetUsersView(u=>true);
}
I'd like to know if there is a way or more efficient way using Linq. Instead of using the while loop, is it possible to do a select where using Linq query?
public UserPrincipal GetUser(string sUserName, string spwd, string domain, string ou)
{
PrincipalContext oPrincipalContext = new PrincipalContext(ContextType.Domain, domain, ou, sUserName, spwd);
UserPrincipal oUserPrincipal = UserPrincipal.FindByIdentity(oPrincipalContext, sUserName);
DirectoryEntry user = (DirectoryEntry)oUserPrincipal.GetUnderlyingObject();
PropertyCollection pc = user.Properties;
IDictionaryEnumerator ide = pc.GetEnumerator();
ide.Reset();
while (ide.MoveNext())
{
PropertyValueCollection pvc = ide.Entry.Value as PropertyValueCollection;
if (ide.Entry.Key.ToString() == "XYZ")
{
//Response.Write(string.Format("name: {0}", ide.Entry.Key.ToString()));
//Response.Write(string.Format("Value: {0}", pvc.Value));
}
}
.......;
.......;
}
Thanks!
The reason you can't use Where() on a PropertyCollection is because it implements the non-generic IEnumerable, when Where() is a method of only the generic version. You can convert a PropertyCollection to a generic IEnumerable by using Cast<T>().
var matches = pc.Cast<DictionaryEntry>().Where(p => p.Key.ToString() == "XYZ");
foreach( var match in matches )
{
Response.Write(string.Format("name: {0}", match.Key));
Response.Write(string.Format("Value: {0}", match.Value));
}
This way is doubtfully any more efficient.
Try this:
foreach (PropertyValueCollection pvc in pc.OfType<PropertyValueCollection>().Where(v => v.PropertyName == "XYZ"))
{
Response.Write(string.Format("name: {0}", pvc.PropertyName));
Response.Write(string.Format("Value: {0}", pvc.Value));
}
Besides, you can try to use ForEach:
pc.OfType<PropertyValueCollection>()
.Where(v => v.PropertyName == "XYZ")
.ToList()
.ForEach(pvc =>
{
Response.Write(string.Format("name: {0}", pvc.PropertyName));
Response.Write(string.Format("Value: {0}", pvc.Value));
});
This is a pretty old thread, but I was searching for a way to work with PropertyCollection using LINQ. I tried the suggested methods, but I always get an invalid cast exception when casting to DictionaryEntry. And with a DictionaryEntry, things like FirstOrDefault are funky. So, I simply do this:
var directoryEntry = adUser.GetUnderlyingObject() as DirectoryEntry;
directoryEntry.RefreshCache();
var propNames = directoryEntry.Properties.PropertyNames.Cast<string>();
var props = propNames
.Select(x => new { Key = x, Value = directoryEntry.Properties[x].Value.ToString() })
.ToList();
With that in place, I can then easily query for any property directly by Key. Using the coalesce and safe navigation operators allows for defaulting to an empty string or whatever..
var myProp = props.FirstOrDefault(x => x.Key == "someKey"))?.Value ?? string.Empty;
Note that the "adUser" object is the UserPrincipal object.
Spurred on by this question, I decided to try this in my MVC3/ActiveRecord application.
I have a bunch of models already working, and some views that do stuff with those models. Nothing special here. One of my models is called AppSession.
Based on said question, I expected this to work: AppSession.FirstOrDefault(a => ...) ?? null.
It didn't work. I still get an InvalidOperationException. This is true of FirstOrDefault and SingleOrDefault. I ended up wrapping my call in try/catch to get around it.
What am I doing wrong here?
Edit: As requested, the actual code is:
void getAnAppSession() {
AppSession sessions = project.AppSessions.FirstOrDefault(a => a.Ip == ip && a.MacAddress == macAddress && a.Platform == platform && a.Version == version && a.EndTime == null)
}
ip, macAddress, platform, and version are all method variables that are verifiably not null. My schema for AppSessions (and accordingly, properties on my class) includes:
ID (int, not null)
StartDate (DateTime, not null)
EndDate (DateTime, null)
Ip (string, not null)
MacAddress (string, not null)
Platform (string, not null)
Version (string, not null)
Maybe your project.AppSessions itself is null? That would cause the FirstOrDefault() method to throw an error. You might want to check if that is null before calling FirstOrDefault and create a new AppSession object if it is null:
AppSession sessions = (project.AppSessions as AppSession ?? new AppSession())
.FirstOrDefault(a => a.Ip == ip &&
a.MacAddress == macAddress &&
a.Platform == platform &&
a.Version == version &&
a.EndTime == null);