针对实体框架InMemory进行测试

时间:2018-04-19 16:23:18

标签: c# unit-testing entity-framework-core in-memory-database

我目前正在使用内存数据库测试实体框架 DbContext

为了使测试尽可能原子化,DbContext每个测试方法都是唯一的,并且它填充了每个测试所需的初始数据。

要设置DbContext的初始状态,我创建了一个void SetupData方法,用我将在测试中使用的某些实体填充上下文。

这种方法的问题在于,测试期间无法访问在安装过程中创建的对象,因为实体框架将分配自身的ID,直到运行时才知道。

为了克服这个问题,我认为我的SetupData方法可能会变成这样:

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;}
}

如您所见,它返回了我称之为" Fixture" 的实例。 (我不知道名字是否合适)

这样,SetupData会返回一个对象(Fixture,并引用实体。因此,测试可以使用创建的对象。否则,该对象将无法识别,因为在调用SaveChanges之前不会创建Id。

我的问题是:

  • 这是一种不好的做法吗?
  • 有没有更好的方法来引用初始值 数据?

2 个答案:

答案 0 :(得分:2)

我更喜欢这种方法:

public void SetupData(MyContext context) 
{
    var user = new User() { Id = Fixture.TEST_USER1_ID, UserName = Fixture.TEST_USER1_NAME };
    context.Users.Add(user);
    context.SaveChanges();
}

public class Fixture 
{
    public const int TEST_USER1_ID = 123;
    public const string TEST_USER!_NAME = "testuser";
}

您的方法也可能很好,但您可能希望在测试中的某个位置知道用户ID,这使得在单个已知位置指定它非常容易,以便在例如您不会改变时稍后更改您的测试数据和添加用户的顺序。

答案 1 :(得分:1)

这不是一个坏习惯。实际上,创建可读的Given-When-Then测试是一种很好的方法。如果你考虑:

  • 拆分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));
}

......和其他实体类似。

相关问题