java - 如何通过自动装配服务在 spring-boot 上测试控制器层?
问题描述
我正在尝试在我的 API 中测试我的控制器的功能。我已经实现了以下服务,称为ExpertsServiceImpl.java
:
@Service
@RequiredArgsConstructor
public class ExpertsServiceImpl implements ExpertsService{
private final ExpertRepository repository;
@Override
public Experts createExpert(Experts expert) {
return repository.save(expert);
}
@Override
public void deleteExpert(ObjectId id) {
Experts deleted = findExpertById(id);
if(deleted == null) {
throw new ExpertNotFoundException(id);
}
repository.delete(deleted);
}
public Experts findExpertById(ObjectId id) {
Optional<Experts> searchedExpert = repository.findById(id);
if(searchedExpert.get() == null) {
throw new ExpertNotFoundException(id);
}
return searchedExpert.get();
}
这是我的MongoDB
存储库:
public interface ExpertRepository extends MongoRepository<Experts, ObjectId>{
}
这是我的控制器类:
@RestController
@Validated
class ExpertController {
public final ExpertsService service;
public ExpertController(ExpertsService service) {
this.service = service;
}
@PostMapping(path = "/experts/",
consumes = {MediaType.APPLICATION_JSON_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE}
)
public Experts newExpert(@Valid @RequestBody Experts newExpert) {
return service.createExpert(newExpert);
}
@DeleteMapping("/experts/{id}")
public void deleteBook(@PathVariable ObjectId id) throws Throwable {
service.deleteExpert(id);
}
我正在为我的控制器编写以下测试类:
@ActiveProfiles("test")
@RunWith(SpringRunner.class)
@WebMvcTest(controllers = ExpertController.class)
class ExpertControllerTest {
@Autowired
private MockMvc mockMvc;
@Autowired
private ObjectMapper objectMapper;
@Autowired
private ExpertsService expertsService;
@MockBean
private ExpertRepository repository;
Experts demoExpert = new Experts(ObjectId.get(),"Steve Jobs", "Enterpreneur",
Availability.BUSY, Language.CHINESE);
@Before
public void setUp() throws Exception{
expertsService.deleteAll();
expertsService.createExpert(demoExpert);
}
@After
public void tearDown() throws Exception{
expertsService.deleteAll();
}
@Test
public void deleteExpert() throws Exception {
String expertId = demoExpert.getId();
this.mockMvc.perform(MockMvcRequestBuilders
.delete("/experts/{id}", expertId)
.contentType(MediaType.APPLICATION_JSON)
.accept(MediaType.APPLICATION_JSON))
.andExpect(MockMvcResultMatchers.status().isOk());
}
引发此错误:
java.lang.IllegalStateException: Failed to load ApplicationContext
at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:123)
at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.postProcessFields(MockitoTestExecutionListener.java:95)
at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.injectFields(MockitoTestExecutionListener.java:79)
at org.springframework.boot.test.mock.mockito.MockitoTestExecutionListener.prepareTestInstance(MockitoTestExecutionListener.java:54)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:98)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$5(ClassBasedTestDescriptor.java:337)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:342)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$6(ClassBasedTestDescriptor.java:337)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:195)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654)
at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
at java.base/java.util.stream.StreamSpliterators$WrappingSpliterator.forEachRemaining(StreamSpliterators.java:312)
有谁知道我该如何解决这个问题?我想这与我正在自动装配服务和模拟存储库这一事实有关,但不知道如何解决这个问题。我想自动连接服务,因为它对我的测试没有多大意义。任何人都知道我该怎么做?我很感激任何帮助
解决方案
如果您不想模拟该服务,您可以@Import(ExpertsServiceImpl.class)
在您的测试类之上添加或@SpringBootTest
如前所述使用(但在这种情况下,它将加载整个应用程序,这并不是很好,性能方面)
推荐阅读
- java - Java Android 从 Firestore 中获取集合的名称
- android - 我正在使用 youtube android player api 在我的应用程序中播放未列出的 youtube 视频,一次有多少用户可以访问它
- r - 滚动回归 4 年的每日数据,每个新回归和不同的因变量提前一个月
- c++ - 为什么我们要向 ostream obj 发送 ref 到 ostream 重载?
- java - 对象添加到父类arraylist如何访问扩展函数
- mysql - MySQL 列显示另一个表中列的总和
- java - 从另一个布局提交按钮
- javascript - 获取显示在邮递员和 chrome 中永久发送请求的请求
- php - 管理员将产品下载链接更改为自定义链接
- capacitor - 来自电容相机的 GPS EXIF 数据