弹簧数据:服务层单元测试

2022-09-01 17:38:24

在我的项目中,我在进行单元测试时遇到了麻烦。一个问题是,仅仅进行集成测试的编写速度要快得多,并且还可以测试组件是否实际协同工作。对新颖的“算法”进行单元测试似乎要容易得多。单元测试服务类它只是感觉错误和无用。

我正在使用mockito来模拟弹簧数据存储库(因此是数据库访问)。问题是,如果我告诉模拟的存储库在方法调用getById上返回实体A,它显然会返回该实体,并且服务也会返回它。是的,该服务会执行一些额外的操作,但会执行非常小的操作,例如加载延迟集合(从休眠状态)。显然,我在单元测试中没有任何惰性集合(代理)。

例:

@Test
public void testGetById() {
    System.out.println("getById");
    TestCompound expResult = new TestCompound(id, "Test Compound", "9999-99-9", null, null, null);

    TestCompoundRepository mockedRepository = mock(TestCompoundRepository.class);
    when(mockedRepository.findOne(id)).thenReturn(expResult);

    ReflectionTestUtils.setField(testCompoundService, "testCompoundRepository",
            mockedRepository, TestCompoundRepository.class);

    TestCompound result = testCompoundService.getById(id);
    assertEquals(expResult, result);
}

万岁,其余的都成功了。真是惊喜!其实不行。

有人可以向我解释我做错了什么吗?否则,这种测试的意义何在?我的意思是我告诉返回expResult,然后它被返回。哇。真是惊喜!感觉我正在测试mockito是否有效,而不是我的服务。

编辑:

我看到的唯一好处是,如果有些是愚蠢的错误,就会发生这样的情况,比如在那里留下一个不需要的行,将返回值设置为null或类似的愚蠢行为。此类情况将由单元测试捕获。“奖励-努力”的比例似乎还不好吗?


答案 1

问题可能有点旧,但我会给出一个答案,以防有人偶然发现。

  • 我正在使用Mockito和JUnit。
  • AccountRepository是一个普通的弹簧数据存储库,扩展了JPARepository。
  • 帐户是普通的 JPA 实体。

要测试您的服务和模拟Spring Data存储库,您需要如下所示的内容。

package foo.bar.service.impl;

import foo.bar.data.entity.Account;
import foo.bar.data.repository.AccountRepository;
import foo.bar.service.AccountService;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class AccountServiceImplTest {

    @Mock
    private static AccountRepository accountRepository;

    @InjectMocks
    private static AccountService accountService = new AccountServiceImpl();

    private Account account;

    @Test
    public void testFindAccount() {

        Integer accountId = new Integer(1);

        account = new Account();
        account.setId(accountId);
        account.setName("Account name");
        account.setCode("Accont code");
        account.setDescription("Account description");

        Mockito.when(accountRepository.findOne(accountId)).thenReturn(account);

        Account retrivedAccount = accountService.findAccount(accountId);

        Assert.assertEquals(account, retrivedAccount);

    }

}

答案 2

我喜欢测试我的Spring Data存储库的原因之一是测试我是否正确定义了我的JPA映射。我不使用这些模拟框架进行这些测试,我使用Spring Test框架,它实际上引导了容器,允许我将实际的存储库自动连接到Junit测试中,以便我可以对它执行测试。

我同意你的想法,嘲笑存储库是相当无用的。由于您使用Spring,我建议您利用Spring Test框架对您的存储库执行实际测试,这些测试可以针对嵌入式数据库(如H2)以更基于单元测试的方式执行,也可以针对您的实际数据库实现(如Oracle或MySql)执行,以进行更多的集成测试。(针对开发数据库的副本执行这些操作)这些测试将揭示 JPA 映射中的谬误和其他项目,例如数据库中的级联设置不正确。

以下是我在 GitHub 上的一个测试示例。请注意框架实际上如何将存储库自动连接到测试中。该存储库还包含如何配置Spring Test框架的示例,我也在这篇博客文章中演示了该示例

总之,我不相信你会从使用存储库的模拟中获得我讨论过的测试存储库的任何好处。

我想补充的一点是,模拟并不是真正用于实际测试的类。它们的用途是为受测类提供所需的依赖项。


推荐