Why is my Moq not returning null? - c#

My Moq is returning data I don't expect.
var artist = new Artist();
artist.Id = "4576";
var deserializer = Mock.Of<IXmlDeserializer<Album>>(
d => d.Deserialize("foo").Artist == artist);
Assert.IsNull(deserializer.Deserialize(null));
The above test fails.
The really puzzling thing is that the mock returns a Mock but that
Assert.AreEqual("4576", deserializer.Deserialize(null).Artist.Id)
returns true.
It's as if the "default" returned by my mock for an unspecified argument (in this case null) was somehow influenced by what I told it to return when called with "foo".

You can either write:
var artist = new Artist { Id = "4576" };
var mock = new Mock<IXmlDeserializer<Album>>();
mock.Setup(x => x.Deserialize(It.Is<string>(i => i == "foo"))).Returns(new Album() { Artist = artist });
var deserializer = mock.Object;
Assert.IsNull(deserializer.Deserialize(null));
Assert.IsNotNull(deserializer.Deserialize("foo"));
Or using the Mock.Of() syntax the above would be:
var artist = new Artist { Id = "4576" };
var deserializer = Mock.Of<IXmlDeserializer<Album>>(d => d.Deserialize(It.Is<string>(i => i == "foo")) == Mock.Of<Album>(album => album.Artist == artist));
Assert.IsNull(deserializer.Deserialize(null));
Assert.IsNotNull(deserializer.Deserialize("foo"));
Assert.AreEqual("4576", deserializer.Deserialize("foo").Artist.Id);

Related

Entity Framework Core - Get multiple rows from one table as one DTO with multiple properties

Is it possible to select two rows into one anonymous object DTO with two properties?
With a model like:
public class Document
{
public int Id { get; set; }
public string Text { get; set; }
// Other properties
}
I am writing a method that finds the difference between two versions of a document:
public Task<string> CompareVersions(int initialId, int finalId)
So I need to retrieve the text of exactly two Documents by Id, and I need know which was which.
Currently I am constructing a Dictionary<int, string> by doing:
var dto = await _context.Documents
.Where(doc => doc.Id == initialId
|| doc.Id == finalId)
.ToDictionaryAsync(x => x.Id, x => x.Text);
and then calling dto[initialId] to get the text. However, this feels very cumbersome. Is there any way to take the two Ids and select them into one DTO in the form
{
InitialText,
FinalText
}
You have to use SelectMany
var query =
from initial in _context.Documents
where initial.Id = initialId
from final in _context.Documents
where final.Id = finalId
select new
{
InitialText = initial.Text,
FinalText = final.Text
};
var result = await query.FirstOrDefaultAsync();
Aggregate can do it too
var dto = (await _context.Documents
.Where(doc => doc.Id == initialId || doc.Id == finalId).ToListAsync())
.Aggregate(
new { InitialText = "", FinalText = "" },
(seed, doc) => {
if(doc.Id == initialId)
seed.InitialText = doc.Text;
else
seed.FinalText = doc.Text;
}
);
I'm not sure I like it any more than I do your dictionary approach, but with an actual dto at the end rather than the dictionary:
var d = await _context.Documents
.Where(doc => doc.Id == initialId || doc.Id == finalId)
.ToDictionaryAsync(x => x.Id, x => x.Text);
var dto = new { InitialText = d[initialId], FinalText = d[finalId] };
You could also perhaps just:
var dto = new {
InitialText = await context.Documents
.FindAsync(initialId),
FinalText = await context.Documents
.FindAsync(finalId)
};

Unit Testing xUnit Asserting 2 Collections with Moq Interface

Good day everyone,
I'm new in xunit and even in unit testing. I have a code here and I'm trying to assert two collection of list. But I have no idea how to assert and pass this test. Here's my code
[Theory]
[InlineData(1)]
public void GetAllStudents_Exempt1(int number)
{
// arrange
var studentRepo = new Mock<IStudentRepository>();
var listOfStudents = new List<Student> { new Student { StudentId = 1, Firstname = "Firstname1", Lastname = "Firstname1" },
new Student{StudentId=2, Firstname="Firstname2",Lastname="Lastname2"} };
var getAllStudentDetailsExempt1 = studentRepo.Setup(s => s.GetStudents()).Returns(listOfStudents.Where(x => x.StudentId != number));
var studentService = new StudentService(studentRepo.Object);
// act
var getStudentsDetails = studentService.ListOfStudentsExempt1(1);
// assert
// I don't have any idea how to assert
}
First a few notes:
var getAllStudentDetailsExempt1 = studentRepo
.Setup(s => s.GetStudents())
.Returns(listOfStudents.Where(x => x.StudentId != number));
you don't need var getAllStudentDetailsExempt1, you can just setup your repo-mock...
studentRepo
.Setup(s => s.GetStudents())
.Returns(listOfStudents.Where(x => x.StudentId != number));
You probably want to change:
// act
var getStudentsDetails = studentService.ListOfStudentsExempt1(1);
to use the number variable...
// act
var getStudentsDetails = studentService.ListOfStudentsExempt1(number);
So then you can assert by checking some properties:
Assert.Equals(1, getStudentsDetails.Count);
Assert.Equals("FirstName1", getStudentsDetails.First().Firstname);
etc. etc.
Give it a shot!

How do you reuse mapping functions on Nested entities in Entity Framework?

I have seen multiple questions that are similar to this one but I think my case is slightly different. I'm using EF6 to query the database and I'm using data projection for better queries.
Given that performance is very important on this project I have to make sure to just read the actual fields that I will use so I have very similar queries that are different for just a few fields as I have done this I have noticed repetition of the code so I'm been thinking on how to reuse code this is currently what I Have:
public static IEnumerable<FundWithReturns> GetSimpleFunds(this DbSet<Fund> funds, IEnumerable<int> fundsId)
{
IQueryable<Fund> query = GetFundsQuery(funds, fundsId);
var results = query
.Select(f => new FundWithReturns
{
Category = f.Category,
ExpenseRatio = f.ExpenseRatio,
FundId = f.FundId,
Name = f.Name,
LatestPrice = f.LatestPrice,
DailyReturns = f.FundDailyReturns
.Where(dr => dr.AdjustedValue != null)
.OrderByDescending(dr => dr.CloseDate)
.Select(dr => new DailyReturnPrice
{
CloseDate = dr.CloseDate,
Value = dr.AdjustedValue.Value,
}),
Returns = f.Returns.Select(r => new ReturnValues
{
Daily = r.AdjDaily,
FiveYear = r.AdjFiveYear,
MTD = r.AdjMTD,
OneYear = r.AdjOneYear,
QTD = r.AdjQTD,
SixMonth = r.AdjSixMonth,
ThreeYear = r.AdjThreeYear,
YTD = r.AdjYTD
}).FirstOrDefault()
})
.ToList();
foreach (var result in results)
{
result.DailyReturns = result.DailyReturns.ConvertClosingPricesToDailyReturns();
}
return results;
}
public static IEnumerable<FundListVm> GetFundListVm(this DbSet<Fund> funds, string type)
{
return funds
.Where(f => f.StatusCode == MetisDataObjectStatusCodes.ACTIVE
&& f.Type == type)
.Select(f => new FundListVm
{
Category = f.Category,
Name = f.Name,
Symbol = f.Symbol,
Yield = f.Yield,
ExpenseRatio = f.ExpenseRatio,
LatestDate = f.LatestDate,
Returns = f.Returns.Select(r => new ReturnValues
{
Daily = r.AdjDaily,
FiveYear = r.AdjFiveYear,
MTD = r.AdjMTD,
OneYear = r.AdjOneYear,
QTD = r.AdjQTD,
SixMonth = r.AdjSixMonth,
ThreeYear = r.AdjThreeYear,
YTD = r.AdjYTD
}).FirstOrDefault()
}).OrderBy(f=>f.Symbol).Take(30).ToList();
}
I'm trying to reuse the part where I map the f.Returns so I tried created a Func<> like the following:
private static Func<Return, ReturnValues> MapToReturnValues = r => new ReturnValues
{
Daily = r.AdjDaily,
FiveYear = r.AdjFiveYear,
MTD = r.AdjMTD,
OneYear = r.AdjOneYear,
QTD = r.AdjQTD,
SixMonth = r.AdjSixMonth,
ThreeYear = r.AdjThreeYear,
YTD = r.AdjYTD
};
and then use like this:
public static IEnumerable<FundListVm> GetFundListVm(this DbSet<Fund> funds, string type)
{
return funds
.Where(f => f.StatusCode == MetisDataObjectStatusCodes.ACTIVE
&& f.Type == type)
.Select(f => new FundListVm
{
Category = f.Category,
Name = f.Name,
Symbol = f.Symbol,
Yield = f.Yield,
ExpenseRatio = f.ExpenseRatio,
LatestDate = f.LatestDate,
Returns = f.Returns.Select(MapToReturnValues).FirstOrDefault()
}).OrderBy(f=>f.Symbol).Take(30).ToList();
}
The compiler is ok with it but at runtime, it crashes and says: Internal .NET Framework Data Provider error 1025
I tried to convert the Func into Expression like I read on some questions and then using compile() but It didn't work using AsEnumerable is also not an option because It will query all the fields first which is what I want to avoid.
Am I trying something not possible?
Thank you for your time.
It definitely needs to be Expression<Func<...>>. But instead of using Compile() method (not supported), you can resolve the compile time error using the AsQueryable() method which is perfectly supported (in EF6, the trick doesn't work in current EF Core).
Given the modified definition
private static Expression<Func<Return, ReturnValues>> MapToReturnValues =
r => new ReturnValues { ... };
the sample usage would be
Returns = f.Returns.AsQueryable().Select(MapToReturnValues).FirstOrDefault()

Entity Framework condition in select

I have the following database code:
static IEnumerable<dynamic> GetData(bool withchildren) {
using (var model = new testEntities()) {
var res = default(IQueryable<dynamic>);
if (withchildren) {
res = model.UserSet
.Where(u => u.name != "")
.Select(u => new {
Name = u.name,
Email = u.email,
Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
})
});
} else {
res = model.UserSet
.Where(u => u.name != "")
.Select(u => new {
Name = u.name,
Email = u.email
});
}
return res.ToList()
}
}
I would like to shrink the code and write it like this:
static IEnumerable<dynamic> GetData(bool withchildren) {
using (var model = new testEntities()) {
var res = default(IQueryable<dynamic>);
res = model.UserSet
.Where(u => u.name != "")
.Select(u => {
dynamic item = new {
Name = u.name,
Email = u.email
};
if(withchildren) {
item.Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
});
}
return item;
});
return res.ToList();
}
}
But Visual Studio complains, that it cannot convert the lambda expression into an expression tree.
My question is, is there a way to accomplish that with the Entity Framework and Linq? I really wouldn't want to use ADO.net directly.
Maybe there is even a better version to shrink it, than the code that I imagine.
Here is a related question with Linq-To-Objects.
EDIT
Before someone asks, I use dynamic in the example code to make it a bit easier and faster.
EDIT 2
My goal with this approach is, to only query the fields I need to improve performance. Check http://www.progware.org/Blog/post/Slow-Performance-Is-it-the-Entity-Framework-or-you.aspx.
At the moment we use something like
static IEnumerable<dynamic> GetData(bool withchildren) {
using (var model = new testEntities()) {
var res = default(IQueryable<dynamic>);
res = model.UserSet
.Where(u => u.name != "")
.ToList();
return res;
}
}
And the performance is, according to Glimpse, horrible.
EDIT 3
Short side note, I made up some quick and dirty code. That is, why the foreach at the end was not needed. The actual code is not available at the moment.
Is there any reason you couldn't use:
res = model.UserSet
.Where(u => u.name != "")
.Select(u => new {
Name = u.name,
Email = u.email,
Groups = withchildren
? u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
})
: null;
})
};
or perhaps:
res = model.UserSet
.Where(u => u.name != "")
.ToList() // ToList() here to enumerate the items
.Select(u => {
dynamic item = new {
Name = u.name,
Email = u.email
};
if(withchildren) {
item.Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
});
}
return item;
});
One approach that would allow you to eliminate some code would be:
var res = model.UserSet.Where(u => u.name != "");
if (withchildren) {
res = res.Select(u => new {
Name = u.name,
Email = u.email,
Groups = u.GroupSet.Select(g => new {
Name = g.name,
Id = g.Id
})
});
} else {
res = res.Select(u => new {
Name = u.name,
Email = u.email
});
}
One of the most requested by community feature is support of multi-line expressions in EF,
however so far, you can use only conditional operator "?:" as well as wrap result in
one common type, so both your results will have to have "Groups" field.
Also there are an extensions to linq-providers such as https://www.nuget.org/packages/LinqKit/ ,
however they are based on own conventions so any developer should study it in depth before
taking advance in applying and supporting code written upon that extensions.

XMLDescendants to Object

I am parsing XML to create an object. I am just unsure as to how to cast the var lotConfig into a LotCOnfig object.
I have tried :
var lotConfig = (LotConfig) xml.Descendants("LOT_CONFIGURATON").Select(
and
return lotConfig as LotConfig
But None have worked so far.
public LotConfig GetLotConfigData(FileInfo lotFile)
{
var xml = XElement.Load(lotFile.FullName);
var lotConfig = xml.Descendants("LOT_CONFIGURATON").Select(
lot => new LotConfig
{
LotNumber = (string) lot.Element("LOT_NUMBER").Value,
LotPartDescription = lot.Element("PART_DESCRIPTION").Value,
LotDate = lot.Element("LOT_DATE").Value,
ComponentList = lot.Descendants("ASSY_COMPONENT").Select(ac => new LotComponent
{
PartNumber = ac.Descendants("COMPONENT_PART_NUMBER").FirstOrDefault().Value,
ArtworkNumber = ac.Descendants("ARTWORK_NUMBER").FirstOrDefault().Value,
RefDesignator = ac.Descendants("REFERENCE_DESIGNATOR").FirstOrDefault().Value
}).ToList()
});
return lotConfig as LotConfig;
}
Currently lotConfig is of type IEnumerable<LotConfig>, you need to call .FirstOrDefault() at the end of your LINQ to make it return single LotConfig type :
var lotConfig = xml.Descendants("LOT_CONFIGURATON")
.Select(
lot => new LotConfig
{
LotNumber = (string) lot.Element("LOT_NUMBER").Value,
LotPartDescription = lot.Element("PART_DESCRIPTION").Value,
LotDate = lot.Element("LOT_DATE").Value,
ComponentList = lot.Descendants("ASSY_COMPONENT").Select(ac => new LotComponent
{
PartNumber = ac.Descendants("COMPONENT_PART_NUMBER").FirstOrDefault().Value,
ArtworkNumber = ac.Descendants("ARTWORK_NUMBER").FirstOrDefault().Value,
RefDesignator = ac.Descendants("REFERENCE_DESIGNATOR").FirstOrDefault().Value
}).ToList()
})
.FirstOrDefault();

Categories

Resources