【发布时间】:2021-11-17 15:59:02
【问题描述】:
在我的 Java 应用程序中,我尝试使用单元测试来测试以下服务方法:
@Service
@EnableCaching
@RequiredArgsConstructor
public class LabelServiceImpl implements LabelService {
private static final String CACHE_NAME = "demoCache";
private final LabelRepository labelRepository;
@Override
public List<LabelDTO> findByUuid(UUID uuid) {
final Label label = labelRepository.findByUuid(uuid)
.orElseThrow(() -> new EntityNotFoundException("Not found."));
final List<LabelDTO> labelList = labelRepository.findByUuid(uuid);
return labelList;
}
}
这是我的单元测试:
@Import({CacheConfig.class, LabelServiceImpl.class})
@ExtendWith(SpringExtension.class)
@EnableCaching
@ImportAutoConfiguration(classes = {
CacheAutoConfiguration.class,
RedisAutoConfiguration.class
})
@RunWith(MockitoJUnitRunner.class)
public class CachingTest {
@InjectMocks
private LabelServiceImpl labelService;
@Autowired
private CacheManager cacheManager;
@Mock
private LabelRepository labelRepository;
@Test
void givenRedisCaching_whenFindUuid_thenReturnFromCache() {
//code omitted
LabelDTO labelFromDb = labelService.findByUuid(uuid);
LabelDTO labelFromCache = labelService.findByUuid(uuid);
verify(labelRepository, times(1)).findByUuid(uuid);
}
}
当我在单元测试中将@Autowired 用于LabelServiceImpl 时,我收到“Nullpointer 异常”错误。如果我对该实例使用@InjectMocks 注释,则不会出现错误,但不会进行缓存(它调用labelService.findByUuid 2 次而不是1 次)。
我认为我犯了与单元测试类中的注释有关的错误,但我尝试了许多不同的组合并不能解决问题。
那么,我该如何解决这个问题?
更新:最后我使用以下方法解决了这个问题。但是,我还必须将mockito-core 版本从3.3.3 更新为3.7.0,如下所示。否则我会收到“java.lang.NoSuchMethodError: org.mockito.MockitoAnnotations.openMocks(Ljava/lang/Object;)Ljava/lang/AutoCloseable;”错误。
pom.xml:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.7.0</version>
<scope>test</scope>
</dependency>
缓存测试:
@ExtendWith(MockitoExtension.class)
@SpringBootTest
public class CachingTest {
@Autowired
@InjectMocks
private LabelServiceImpl labelService;
@MockBean
private LabelRepository labelRepository;
@Test
public void givenRedisCaching_whenFindUuid_thenReturnFromCache() {
//code omitted
LabelDTO labelFromDb = labelService.findByUuid(uuid);
LabelDTO labelFromCache = labelService.findByUuid(uuid);
verify(labelRepository, times(1)).findByUuid(uuid);
assertEquals(labelFromDb, labelFromCache);
}
}
【问题讨论】:
-
请不要再问同样的问题,而是改写或澄清您就此提出的其他问题。正如我在另一篇文章中所说,您的测试没有意义,大多数注释都是无用的,您期望在没有向测试中添加弹簧功能的模拟模拟将测试弹簧功能。这当然不会发生。 Autowire
LabelService不是 impl,放弃所有注释,只需添加@SpringBootTest并将@Mock替换为@MockBean。我记得对您的另一个问题(似乎已被删除)给出了相同的答案/评论。 -
非常感谢。如果我使用
@SpringBootTest注释,我会得到labelService的“java.lang.NullPointerException”(我也将其更改为接口 ->LabelService)。 -
另一方面,如果我在
@SpringBootTest之外添加@RunWith(SpringRunner.class),那么我会得到 "java.lang.IllegalArgumentException: Cannot find cache named 'demoCache' for Builder[public java. util.List com.mycompany.service.impl.LabelServiceImpl.findByUuid(UUID)] caches=[demoCache] | key='' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | 除非='' | sync='false'" 错误。 但是我认为我们非常接近解决方案,因为它会查找缓存,但无法找到该名称。 -
我也试过在我的测试类上添加
@EnableCaching注解,但还是同样的问题。 -
如果您使用的是 junit4(我假设为 5),您还需要
@RunWith。您需要配置缓存管理器以创建该缓存(显然您使用的缓存不支持即时创建)。
标签: java spring spring-boot unit-testing junit