我在编写使用假存储库的集成测试时遇到了麻烦,
例如:假设我有一个教室实体,它聚集了学生......
var classroom = new Classroom();
classroom.Students.Add(new Student("Adam"));
_fakeRepository.Save(classroom);
_fakeRepostiory.GetAll<Student>().Where((student) => student.Name == "Adam"));
// This query will return null...
当我使用真正的存储库实现(基于NHibernate)时,上面的代码可以工作(因为保存操作会级联到前一行添加的学生),
您知道支持此行为的任何虚假存储库实现吗? 关于如何自己实施的想法?
或者你有什么其他建议可以帮助我避免这个问题吗?
提前致谢, 埃里克。
答案 0 :(得分:2)
如果您正在编写“集成测试”,因为您的问题正文表明,您不会使用虚假实现 - 使用真实的东西。
如果您正在编写单元测试,正如您的问题标题所示,您不会关心该操作是否级联,因为这不是课堂课程的关注 - 您关心的只是{{1}在类作为依赖项给出的任何存储库中调用。
如果您正在围绕NHibernate执行级联操作的能力编写单元测试,那么这些测试已经编写完成,并且没有证明课堂课程。
单元测试用于测试功能的各个“单元”,独立于任何其他类或服务 - 在这种情况下,您使用伪造用于其他类,以确保它们确实完成并且仅限于此类所需的内容。集成测试用于测试多个类和/或子系统之间的交互(如数据库访问,ORM等)。在这种情况下,似乎你想测试级联保存/更新,但这是NHibernate的责任,不是吗?
但是,假设您有一个使用Save()
保存classroom
的类,并且它将该操作包装在IRepository<Classroom>
块中,并且您希望在{{{{}}时对其进行单元测试1}}抛出try…catch
,错误计数属性,IRepository<Classroom>
递增。在这里你做需要你的存储库的虚假实现,这就是像RhinoMocks,nMock,Moq或TypeMock Isolator这样的模拟框架发挥作用 - 这些可以为你生成假的,使用接口,抽象类或已声明其公共方法和属性的类RepositoryWriteFailureException
我可能会像这样写一个测试的主体(将其视为伪代码):
ErrorCount
请注意我们如何测试virtual.
类或者您正在测试的任何内容的行为,甚至无需实现存储库。
答案 1 :(得分:1)
由于它是集成测试,我建议您使用真实的存储库,而不仅仅是假存储库。
一个好的解决方案是创建一个单独的数据库用于测试目的,并在测试项目的配置文件中将NHibernate的hbm2ddl.auto
属性设置为create
,这样每次都会重新创建数据库,所以你不必担心这个问题。
我将此用于测试目的。我使用FluentNHibernate的自动映射器和自定义约定。如果您想使用更轻的SQL Server进行测试,您可能还想使用SQLite (我使用SQL Server以这种方式对我的存储库进行单元测试。)
如果您希望保留已输入的数据,也可以将其设置为update
,如果您可以手动创建测试数据库,则根本不应设置它
答案 2 :(得分:0)
+1,如果测试不使用真实的东西(即不测试与RDBMS的集成),则不要将其称为“集成测试”。
如果你想要级联和NHibernate的所有其他优点和«单元测试»的速度,我发现使用内存数据库(SQLite)非常有用。