如何测试 Nhibernate 的扩展方法,即使在 fakeiteasy 中指定 return 后也没有 return 值?
How do I test extension method of Nhibernate which does not return the value even after specifying return in fakeiteasy?
我有一个 class 如下所示,我使用 Fluent Nhibernate 从数据库中获取数据
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>();
}
}
}
我已经为上面的方法编写了单元测试用例,如下所示
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();
}
}
实际上如果你看到下面的代码
session.QueryOver()
.SelectList(...
将在方法 GetData() 中 return "result"。之后,我正在操纵 "result" 数据结构以获取 Id、CreationDate、AnnualAmount、AnnualCurrency
因此,从 "result" 中 return 得到一些值是非常重要的。我的问题是 resulty 的计数总是 0.
我想要下面这行代码
A.CallTo(session.QueryOver()).WithReturnType>().Returns(listOfAnnualInformation);
到 return 至少包含一个元素的列表。现在我相信我澄清了我的要求
请建议这里应该做什么?
基于新代码(仍未完全编译 - 缺少 ;
,result
不是 return 来自 GetData
,如果它是的,GetData
的 return 类型应该是 IList<AnnualInformation>
,但通过这些更改,我能够对 运行 进行测试)我可以提供一些评论:
A.CallTo(session.QueryOver<AnnualInformation>()).WithReturnType<IList<AnnualInformation>>()
.Returns(listOfAnnualInformation);
配置从调用 session.QueryOver<AnnualInformation>()
返回的对象。 (注意这里没有 lambda,所以这一行实际上调用了 QueryOver
。)
session
是假的,所以当你在这条线上调用 QueryOver<AnnualInformation>()
时,它将 return 一个新的假 IQueryOver
。当调用 return 和 IList<AnnualInformation>
的任何方法时,"WithReturnType…Returns…" 将新的 Fake IQueryOver 配置为 return listOfAnnualInformation
。
然而,当 Fakes 的方法被调用时,除非它们被配置为做一些不同的事情,否则它们 return 一个新对象。所以在 GetData
中,当你调用 QueryOver
时,你会得到 一个不同的假 IQueryOver
,它根本没有被配置。这是一个问题。
第二个问题:调用 SelectList
将 return 另一个伪造的 IQueryOver
.
我们可以解决所有这些问题:
var aFakeQueryOver = A.Fake<IQueryOver<AnnualInformation, AnnualInformation>>();
A.CallTo(aFakeQueryOver).WithReturnType<IQueryOver<AnnualInformation, AnnualInformation>>()
.Returns(aFakeQueryOver);
A.CallTo(aFakeQueryOver).WithReturnType<IList<AnnualInformation>>()
.Returns(listOfAnnualInformation);
A.CallTo((() => session.QueryOver<AnnualInformation>())).Returns(aFakeQueryOver);
现在伪造行为如我们所愿。然而,我们所做的只是短路 GetData
中的所有逻辑,除了看到它使用 sessionFactory
打开一个会话,然后 QueryOver
在那个会话上。 SelectList
和Where
和List
都被绕过了
在这种情况下,我通常的建议是使您的数据访问层尽可能薄,并对其进行集成测试。或者,我看到有人建议让 NHibernate 使用内存中的 MySql 数据库。仍然是某种集成测试,但至少它更加孤立。
我有一个 class 如下所示,我使用 Fluent Nhibernate 从数据库中获取数据
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>();
}
}
}
我已经为上面的方法编写了单元测试用例,如下所示
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();
}
}
实际上如果你看到下面的代码
session.QueryOver() .SelectList(...
将在方法 GetData() 中 return "result"。之后,我正在操纵 "result" 数据结构以获取 Id、CreationDate、AnnualAmount、AnnualCurrency
因此,从 "result" 中 return 得到一些值是非常重要的。我的问题是 resulty 的计数总是 0.
我想要下面这行代码
A.CallTo(session.QueryOver()).WithReturnType>().Returns(listOfAnnualInformation);
到 return 至少包含一个元素的列表。现在我相信我澄清了我的要求
请建议这里应该做什么?
基于新代码(仍未完全编译 - 缺少 ;
,result
不是 return 来自 GetData
,如果它是的,GetData
的 return 类型应该是 IList<AnnualInformation>
,但通过这些更改,我能够对 运行 进行测试)我可以提供一些评论:
A.CallTo(session.QueryOver<AnnualInformation>()).WithReturnType<IList<AnnualInformation>>()
.Returns(listOfAnnualInformation);
配置从调用 session.QueryOver<AnnualInformation>()
返回的对象。 (注意这里没有 lambda,所以这一行实际上调用了 QueryOver
。)
session
是假的,所以当你在这条线上调用 QueryOver<AnnualInformation>()
时,它将 return 一个新的假 IQueryOver
。当调用 return 和 IList<AnnualInformation>
的任何方法时,"WithReturnType…Returns…" 将新的 Fake IQueryOver 配置为 return listOfAnnualInformation
。
然而,当 Fakes 的方法被调用时,除非它们被配置为做一些不同的事情,否则它们 return 一个新对象。所以在 GetData
中,当你调用 QueryOver
时,你会得到 一个不同的假 IQueryOver
,它根本没有被配置。这是一个问题。
第二个问题:调用 SelectList
将 return 另一个伪造的 IQueryOver
.
我们可以解决所有这些问题:
var aFakeQueryOver = A.Fake<IQueryOver<AnnualInformation, AnnualInformation>>();
A.CallTo(aFakeQueryOver).WithReturnType<IQueryOver<AnnualInformation, AnnualInformation>>()
.Returns(aFakeQueryOver);
A.CallTo(aFakeQueryOver).WithReturnType<IList<AnnualInformation>>()
.Returns(listOfAnnualInformation);
A.CallTo((() => session.QueryOver<AnnualInformation>())).Returns(aFakeQueryOver);
现在伪造行为如我们所愿。然而,我们所做的只是短路 GetData
中的所有逻辑,除了看到它使用 sessionFactory
打开一个会话,然后 QueryOver
在那个会话上。 SelectList
和Where
和List
都被绕过了
在这种情况下,我通常的建议是使您的数据访问层尽可能薄,并对其进行集成测试。或者,我看到有人建议让 NHibernate 使用内存中的 MySql 数据库。仍然是某种集成测试,但至少它更加孤立。