简体   繁体   English

如何正确地对存储库中的CRUD操作进行单元测试?

[英]How To Properly Unit-Test CRUD Operations on a Repository?

Realize this may sound like a broad question - so let me clarify. 意识到这可能听起来像一个广泛的问题 - 所以让我澄清一下。 I have a Repository exposed via an interface, with two concrete implementations - a MockRepository and a EntityFrameworkRepository . 我有一个通过接口公开的存储库,有两个具体的实现 - 一个MockRepository和一个EntityFrameworkRepository

Now, i have a Unit-Test project for which all tests can be run against either repository, via flicking over a line in [TestInitialize] . 现在,我有一个Unit-Test项目,通过[TestInitialize]的一行,可以对任一存储库运行所有测试。

My question is basically "How should i write the tests". 我的问题基本上是“我该如何编写测试”。

Here's what i have: 这就是我所拥有的:

C reate C reate

// Arrange.
var foo = new Foo { .. };

// Act
Repository.Add(foo);
UnitOfWork.Commit();

// Assert
Assert.IsTrue(foo.Id > 0);

R etrieve R etrieve

// Arrange.
var fooToGet = 1;

// Act
var foo = Repository.FindSingle(fooToGet);

// Assert
Assert.IsNotNull(foo);
Assert.AreEqual(foo.Id, fooToGet);

U pdate üPDATE

// Arrange.
var fooToGet = 1;
var nameToChangeFooTo = "FooBar";

// Act
var foo = Repository.FindSingle(fooToGet);
foo.Name = nameToChangeFooTo;
UnitOfWork.Commit();
var fooRetrievedAgain = Repository.FindSingle(fooToGet);

// Assert
Assert.IsNotNull(foo);
Assert.AreEqual(fooRetrievedAgain.Id, fooToGet);
Assert.AreEqual(fooRetrievedAgain.Name, nameToChangeFooTo);

D elete D elete

// Arrange.
var fooToGet = 1;

// Act
var foo = Repository.FindSingle(fooToGet);
Repository.Remove(foo);
UnitOfWork.Commit();
var fooRetrievedAgain = Repository.FindSingle(fooToGet);

// Assert
Assert.IsNull(fooRetrievedAgain);

It's working ok , for both the Mock and EF repository, but my main problem is C (Create). 它的工作 ,同时为模拟和EF库,但我的主要问题是C(创建)。 I'm not sure how to test an Add operation on my Repository. 我不确定如何测试我的存储库上的添加操作。 It doesn't feel right what im doing. 我在做什么感觉不对

It passes for the EF Repository, but to make it pass in my Mock Repository i had to use reflection to update the ID in the in-memory collection (nasty). 它传递给EF Repository,但为了让它通过我的Mock Repository,我不得不使用反射来更新内存中的ID(讨厌)。

So - can you please share some advice on what are the correct ways to test CRUD operations on the Repository Pattern? 那么 - 请您分享一些关于在存储库模式上测试CRUD操作的正确方法的建议吗?

This is an ASP.NET MVC Application, .NET 4, C#, Entity Framework 4 and Unit of Work/Repository Patterns. 这是一个ASP.NET MVC应用程序,.NET 4,C#,实体框架4和工作单元/存储库模式。

Thanks. 谢谢。

EDIT 编辑

Just to clarify guys, these are not all the unit-tests i have. 只是为了澄清一下,这些并不是我所有的单元测试。 I have unit tests for my service layer, as well as business-rule tests. 我有服务层的单元测试,以及业务规则测试。

Both the latter will (and should) fail if my above Repository tests fail. 如果我的上述存储库测试失败,后者将(并且应该)失败。 That is the point here, to unit-test the very basic operations of my Repositories. 这就是重点测试我的存储库的基本操作 Am i wrong? 我错了吗?

One option is to use an in-memory DB like SqlLite to test the behaviour of your mappings, queries and repositories. 一种选择是使用内存数据库(如SqlLite)来测试映射,查询和存储库的行为。 This is discussed by Ayende here , though his example uses NHibernate. 这是Ayende 在这里讨论的,尽管他的例子使用了NHibernate。

Another option which seems to address your immediate concern of setting the Ids of the domain objects is to use test fakes. 另一个似乎解决您设置域对象的ID的问题的选择是使用测试假货。 This is discussed by RhysC here . 这是RhysC 在这里讨论的。

IMO, your create test should: IMO,你的创建测试应该:

  • add an entity to the repository 将实体添加到存储库
  • assert it was assigned an ID 断言它被分配了一个ID
  • retrieve the inserted entity using the ID 使用ID检索插入的实体
  • compare the initial entity with the read entity and make sure their properties are same 将初始实体与读取实体进行比较,并确保它们的属性相同

I've got many unit tests like yours the main difference is that I'm using a deep comparison method to compare object instances. 我有很多像你这样的单元测试,主要区别在于我使用深度比较方法来比较对象实例。 For instance, my U tests look like this: 例如,我的U测试看起来像这样:

  • add an entity to the repository 将实体添加到存储库
  • retrieve the inserted entity using the ID 使用ID检索插入的实体
  • change some of the entity properties 更改一些实体属性
  • update the entity in the repository 更新存储库中的实体
  • retrieve the updated entity using the ID 使用ID检索更新的实体
  • compare the updated entity with the read entity and make sure their properties are same (you can define a specific logic for properties that are not updatable) 将更新的实体与读取实体进行比较,并确保它们的属性相同(您可以为不可更新的属性定义特定逻辑)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM