如何在spring引导单元测试中使用依赖注入?

hec6srdp  于 2021-07-06  发布在  Java
关注(0)|答案(2)|浏览(401)

使用springboot的单元测试是否可以使用依赖注入?用于集成测试 @SpringBootTest 启动整个应用程序上下文和容器服务。但是,是否可以在单元测试粒度上启用依赖注入功能?
下面是示例代码

@ExtendWith(SpringExtension.class)
public class MyServiceTest {

    @MockBean
    private MyRepository repo;

    @Autowired
    private MyService service; // <-- this is null

    @Test
    void getData() {
        MyEntity e1 = new MyEntity("hello");
        MyEntity e2 = new MyEntity("world");

        Mockito.when(repo.findAll()).thenReturn(Arrays.asList(e1, e2));

        List<String> data = service.getData();

        assertEquals(2, data.size());
    }
}

@Service
public class MyService {

    private final MyRepository repo; // <-- this is null

    public MyService(MyRepository repo) {
        this.repo = repo;
    }

    public List<String> getData() {
        return repo.findAll().stream()
                .map(MyEntity::getData)
                .collect(Collectors.toList());
    }
}

或者我应该将sut(服务类)作为pojo管理并手动注入模拟的依赖项吗?我想保持测试速度,但尽量减少样板代码。

14ifxucb

14ifxucb1#

您尚未添加 @Autowired 为…服务 MyRepository 服务等级

@Service
public class MyService {

    private final MyRepository repo; // <-- this is null

    @Autowired
    public MyService(MyRepository repo) {
        this.repo = repo;
    }

    public List<String> getData() {
        return repo.findAll().stream()
                .map(MyEntity::getData)
                .collect(Collectors.toList());
    }
}

服务测试类

@ExtendWith(MockitoExtension.class)
public class MyServiceTest {

    @Mock
    private MyRepository repo;

    @InjectMocks
    private MyService service;

    @Test
    void getData() {
        MyEntity e1 = new MyEntity("hello");
        MyEntity e2 = new MyEntity("world");

        Mockito.when(repo.findAll()).thenReturn(Arrays.asList(e1, e2));

        List<String> data = service.getData();

        assertEquals(2, data.size());
    }
}
pxyaymoc

pxyaymoc2#

正如@m.deinum在评论中提到的,单元测试不应该使用依赖注入。嘲弄 MyRepository 注入 MyService 使用mockito(和junit5):

@ExtendWith(MockitoExtension.class)
public class MyServiceTest {

    @InjectMocks
    private MyService service;

    @Mock
    private MyRepository repo;

    @Test
    void getData() {
        MyEntity e1 = new MyEntity("hello");
        MyEntity e2 = new MyEntity("world");

        Mockito.when(repo.findAll()).thenReturn(Arrays.asList(e1, e2));

        List<String> data = service.getData();

        assertEquals(2, data.size());
    }
}

如果要测试存储库,请使用 @DataJpaTest . 从文档中:
使用此注解将禁用完全自动配置,而只应用与jpa测试相关的配置。

@DataJpaTest
public class MyRepositorTest {

    @Autowired
    // This is injected by @DataJpaTest as in-memory database
    private MyRepository repo;

    @Test
    void testCount() {
        repo.save(new MyEntity("hello"));
        repo.save(new MyEntity("world"));

        assertEquals(2, repo.count());
    }
}

总之,建议的方法是使用mockito(或类似的库)模拟存储库层来测试服务层,并使用mockito测试存储库层 @DataJpaTest .

相关问题