我目前正在使用内存数据库测试实体框架qazxsw poi。
为了使测试尽可能原子化,DbContext
每个测试方法都是唯一的,并且它填充了每个测试所需的初始数据。
为了设置DbContext
的初始状态,我创建了一个DbContext
方法,用我将在测试中使用的一些实体填充上下文。
这种方法的问题在于,测试期间无法访问在安装过程中创建的对象,因为实体框架将分配自身的ID,直到运行时才知道。
为了克服这个问题,我认为我的void SetupData
方法可能会变成这样的:
SetupData
如你所见,它正在返回我称之为“Fixture”的实例。 (我不知道名字是否合适)。
这样,public Fixture SetupData(MyContext context)
{
var fixture = new Fixture();
fixture.CreatedUser = new User();
context.Users.Add(fixture.CreatedUser);
context.SaveChanges();
return fixture;
}
public class Fixture
{
public User CreatedUser { get; set;}
}
将返回一个对象(SetupData
),引用实体。因此,测试可以使用创建的对象。否则,该对象将无法识别,因为在调用Fixture
之前不会创建Id。
我的问题是:
这不是一个坏习惯。实际上,创建可读的Given-When-Then测试是一种很好的方法。如果你考虑:
SaveChanges
方法SetupData
然后你可以编写(一个概念性的例子,需要重新编写细节以匹配你的实现):
public static MyContextExtensions
{
public static User Given(this MyContext @this, User user)
{
@this.Users.Add(user);
@this.SaveChanges();
return user;
}
public static OtherEntity Given(this MyContext @this, OtherEntity otherEntity)
{
// ...
}
// ...
}
......和其他实体类似。
我更喜欢这种方法:
[Test]
public GivenAUser_WhenSearchingById_ReturnsTheUser()
{
var expectedUsername = "username";
var user = _context.Given(AUser.WithName(expectedUsername));
var result = _repository.GetUser(user.Id);
Assert.That(result.Name, Is.EqualTo(expectedUsername));
}
您的方法也可能很好,但您可能希望在测试中的某个位置知道用户ID,这使得在单个已知位置指定它非常容易,因此如果您稍后更改它将不会更改您的测试数据以及添加用户的顺序。