DataJPATest Junit 方法命名和 NullPointerExceptions

DataJPATest Junit method naming and NullPointerExceptions

我正在使用 SpringBoot/Kotlin/JPA/Hibernate/Junit 并使用 JpaServiceTest class 来执行与单个实体相关的存储库方法。 JpaService的方法名Class遵循约定findByXXXXIdfindAllupdateXXXXaddXXXXdeleteXXXX.

为了保持一致性,我使用相同的约定命名了 JpaTest Class 中的方法。我的 JpaTest Class 有两种 findById 场景,一种是 'Null' 是预期的,另一种是映射实体是 returned。我的应用程序按预期工作,但是我的测试 class 在预期 return 有效实体的 findById 场景中失败。

The service class

@Service("MyService")
@Transactional
internal class JpaMyService(val MyRepo: MyRepository) : MyService {

val log = LoggerFactory.getLogger("MyService")

override fun findByMyId(MyId: Long): MyDto? {
    log.debug("Retrieving My: {}", MyId)
    return MyRepo.findOne(MyId)?.toDto()
}

override fun findAllMys(): List<MyDto> {
    log.debug("Retrieving Mys")
    return MyRepo.findAll().map { it.toDto() }
}

override fun updateMy(id: Long?, My: UpdateMyDto): MyDto? {
    log.debug("Updating My: {} with data: {}", id, My)
    val currentMy = MyRepo.findOne(id)
    return if (currentMy != null) MyRepo.save(MyEntity.fromDto(My, currentMy)).toDto()
    else null
}

override fun addMy(My: CreateMyDto): MyDto {
    log.debug("Adding My: {}", My)
    return MyRepo.save(MyEntity.fromDto(My)).toDto()
}

override fun deleteMy(id: Long?) {
    log.debug("Deleting My: {}", id)
    MyRepo.delete(id)
}

违规方法

@Test
fun `'findMyById' should map existing entity from repository`() {
    repository.save(MyEntity(1, "name", "description"))
    val result = service.findByMyId(1)
    softly.assertThat(result?.id).isEqualTo(1)
    softly.assertThat(result?.name).isEqualTo("name")
    softly.assertThat(result?.description).isEqualTo("description")
}

Test failure

org.junit.ComparisonFailure: 
Expected :"name"
Actual   :null

将失败的 findByMyId 方法的名称更改为 getByMyIdretrieveByMyId 允许测试用例从命令行和 IDE 成功通过。如果 运行 作为单个测试,测试将始终从 IDE 开始工作,而不管名称如何,但是当测试 class 是 运行 作为一个整体时,它将失败。

我想知道将 findByXXId 用于 return 和 Entity 的问题是什么,当我将测试方法的名称更改为以 get 或 retrieve 开头时,这会起作用。如果我使用任何其他方法名称,它也会失败,更重要的是,即使我在其他服务和测试中更改方法名称 classes,由于 NPE,我也会看到失败。

如果这没有意义,请提前致歉,但我是这个堆栈的新手,我花了三天时间来确定为什么当应用程序运行良好时这些测试失败了。

由于我在评论中的第一个建议似乎并没有解决它,所以这里列出了一些为了隔离问题而要做的事情。

首先要确保我弄清楚了事实:

  • 您的测试在 IDE
  • 中有效
  • 当 运行 与所有其他测试(可能使用 Maven 或类似工具)一起时,您的测试失败
  • 当 运行 与所有其他测试一起使用时,您的测试有效,但已重命名。

我对评论的预感仍然成立:这与名称没有直接关系,但与测试之间的相互依赖关系有关。

  1. 创建一个最小场景来重现 IDE 中的问题。

    a) 运行 IDE 中的所有测试(应该可以通过 selecting 测试源文件夹和 selecting "Run tests" 或者东西。

    b) 假设测试失败,通过 select 树的越来越小的部分来缩小测试范围。

    c) 如果测试在 IDE 中完全没有失败,您可以在 Maven 或任何其他受人尊敬的构建工具中使用 include/exclude 来做同样的事情。

    d) 另一种变体是创建一个包含所有测试的专用测试套件。

    一般来说,通过在每个步骤中删除大约一半的测试,您应该能够在合理的时间内得到包含两个测试的测试套件:有问题的测试和另一个触发第一个失败的测试。

  2. 为 SQL 和事务处理激活日志记录。

    您应该会在第一次测试后看到回滚。其次是第二个测试的插入。您应该看不到任何提交。

    如果您没有看到回滚,您的测试要么未使用 @Transactional 注释,要么由于某种原因未提取事务。

    如果您没有看到插入内容,您的更改似乎没有刷新。

  3. 使用JDBC模板发出select语句来查看你的数据库的内容。使用像 select * from x 这样的简单语句。没有 where 子句,没有连接。记录结果。

有了这些信息,您的问题很可能变得显而易见。如果没有更新问题并对此答案发表评论。我再看看。