I have a class like below where using Fluent Nhibernate I am getting data from database
public class MyActualClass
{
public MyActualClass(ISessionFactory sessionFactory)
{
this.sessionFactory = sessionFactory;
}
public List<AnnualInformation> GetData()
{
using (session = sessionFactory.OpenSession())
{
var result = session.QueryOver<AnnualInformation>()
.SelectList(list => list
.Select(x => x.Id)
.Select(x => x.CreationDate)
.Select(x => x.AnnualAmount)
.Select(x => x.AnnualCurrency)
.Select(() => monthlyAlias.MonthlyAmount)
.Select(() => monthlyAlias.MonthlyCurrency)
.Select(() => shareAlias.CurrentSharevalue)
.Select(() => miscAlias.MarketValueAmount)
).Where(a => a.Id == 123456).List<AnnualInformation>();
}
}
}
I Have written unit test case for above method like below
public class MyTestClass
{
private static ISessionFactory sessionFactory;
private static ISession session;
public MyTestClass()
{
sessionFactory = A.Fake<ISessionFactory>();
session = A.Fake<ISession>();
A.CallTo(() => sessionFactory.OpenSession()).Returns(session);
}
[Fact]
public void MyTest()
{
var annualDetails =
new AnnualInformation
{
Id= 1,
AnnualCurrency= "string",
AnnualAmount= "Example"
}
var listOfAnnualInformation=
new List<AnnualInformation>
{
annualDetails
};
A.CallTo(session.QueryOver<AnnualInformation>()).WithReturnType<IList<AnnualInformation>>().Returns(listOfAnnualInformation);
var myInstance = new MyActualClass(sessionFactory);
myInstance.GetData();
}
}
Actually if you see below code
session.QueryOver() .SelectList(...
will return "result" in method GetData(). After that I am manipulating "result" datastructure to get Id, CreationDate, AnnualAmount, AnnualCurrency
Therefore it is very important that some value is returned from "result". My problem is the count of resulty is always 0.
I want the below line of code
A.CallTo(session.QueryOver()).WithReturnType>().Returns(listOfAnnualInformation);
to return a list with atleast one element. Now i believe i clarified my requirements
Please suggest what should be done here ?
Based on the new code (which still doesn't quite compile - missing
;
,result
isn't returned fromGetData
, and if it were, the return type ofGetData
should beIList<AnnualInformation>
, but with those changes I was able to get a test to run) I can offer some commentary:Configures the object that comes back from calling
session.QueryOver<AnnualInformation>()
. (Note there's no lambda here, so this line actually callsQueryOver
.)session
is a Fake, and so when you callQueryOver<AnnualInformation>()
on this line, it will return a new FakeIQueryOver
. The "WithReturnType…Returns…" configures the new Fake IQueryOver to returnlistOfAnnualInformation
when any method that returns aIList<AnnualInformation>
is called.However, when Fakes' methods are called, unless they've been configured to do something different, they return a new object. So inside
GetData
when you callQueryOver
, you get a different fakeIQueryOver
, which has not been configured at all. That's one problem.Second problem: the call to
SelectList
will return yet another fakedIQueryOver
.We can work around all these things:
And now the faking behaves as we want. However, all we've done is short-circuit all the logic in
GetData
, except to see that it uses thesessionFactory
to open a session, and thenQueryOver
on that session.SelectList
andWhere
andList
have all been bypassed.My usual advice in this situation is to make your data access layer as thin as possible and to integration test it. Alternatively, I've seen people suggest having NHibernate use an in-memory MySql database. Still an integration test of sorts, but at least it's more isolated.