单元测试处理数据库记录的功能

时间:2018-06-27 17:35:51

标签: java unit-testing tdd

单元测试应仅测试一个功能的逻辑,并应“模拟”该功能中使用的数据。我想知道如何将以下功能与“模拟”数据结合在一起?甚至是正确的方法函数签名是

    public String doSomething(int firstId, int secondId, int count){
     //this function looks in a table e.g. C which has foreign keys from table A, and B
    //if firstId and secondId exist in db table C return "already-exists"
    //if count < a_column_value_in_table_C return "not-allow"
    // else return "success"
    }

firstIdsecondId是形成两个不同表的外键。现在,我们如何根据以下方面对这个功能进行单元测试: 1.应该如何设计单元测试,以便能够在功能中测试3个场景 2.考虑到需要来自两个不同表的外键,我们如何为该单元测试准备数据。

4 个答案:

答案 0 :(得分:3)

您应该使用Solid Principle中的依赖项注入。 拥有doSomething方法所有者的类应注入一些存储库或DAO等。

在单元测试中,您应该模拟存储库方法。

例如,假设您的doSomething方法调用存储库的findById(...)方法。您应该通过所需的输出来模拟findById方法,并仅测试流程的逻辑部分。

答案 1 :(得分:2)

我通常使用getById和getAll函数创建一个存储库接口。为了进行测试,我创建了一个内存库,而为了生产,我使用了数据库库。

这里有个例子:

public interface Repository<T> {
  public T getById(int Id);
  public List<T> getAll();
}

public InmemoryRepository implements Repository<User> {
 List<User> database = new ArrayList<>(); //with some data
 public List<User> getAll() { 
  return database;
 }
 public User get(int Id) {
   return database.stream().filter(x -> x.Id = Id).collect(Collectors.asList());
 }
}

在您的函数中,您注入了该存储库,以便可以通过以下方式访问数据库:

public String doSomething(int firstId, int secondId, int count, Repository<User> repo){};

答案 2 :(得分:2)

您可以使用某些测试数据库或内存数据库(例如HSQLDB)。在测试之前(在带有注释的方法@BeforeClass中或在测试数据源初始化期间,如果使用Spring,则在其中填充一些测试数据)。然后对传递预备数据的所有方案执行测试。用@AfterClass注释的方法清除测试数据库中的数据。

如果您使用Spring并在XML config中配置测试数据源,则可能如下所示:

<jdbc:embedded-database id="dataSource" type="HSQL" >
  <jdbc:script location="scripts/ddl/*"/> <!-- create tables -->
  <jdbc:script location="scripts/dml/*"/> <!-- populate test data -->
</jdbc:embedded-database>

答案 3 :(得分:1)

  1. 您不应该设计一个单元测试来匹配所有情况。对于每种情况,请创建一个不同的单元测试。

  2. 您需要模拟访问数据库的存储库或类,以便它不会在数据库中执行,而是返回您在单元测试中预定的结果集。有为此的模拟库,这使您的工作非常轻松。如果代码仅执行查询或过程并返回结果,则为它编写单元测试没有太多优点,在这种情况下,编写集成测试应该就足够了。

P.S:EmreSavcı,依赖注入不是一个坚实的原则,依赖反转是。它们根本不相关。