【问题标题】:How to make Junit test in spring boot如何在 Spring Boot 中进行 Junit 测试
【发布时间】:2021-01-24 06:25:04
【问题描述】:

我想使用 Mockito.test 测试我的休息控制器方法的行为。

我有以下控制器类

    @RestController
    @RequestMapping("/project/image")
    public class ImageController {
        @Autowired
        ImgService imageService;    
    
    
        @GetMapping("/getImage/{id}")
    public ResponseEntity<Image> getImageById(@PathVariable Integer id) {
        Optional<Image> img = imageService.getImageById(id);
        return new ResponseEntity<Image>(HttpStatus.OK);    
}   ....

我正在尝试对getImageById 方法进行一些基本的单元测试,但它没有通过测试:


@ExtendWith(SpringExtension.class)
@SpringBootTest
@AutoConfigureMockMvc
public class ImageControllerTest {
    @MockBean
    private ImgService service;
    @Autowired
    private MockMvc mockMvc;

    @Test
    @DisplayName("GET /Image/1 - Found")
    void testGetImageIdFound() throws Exception {
        Image mockImage = new Image(1, "mockPath", "Normal");
        doReturn(Optional.of(mockImage)).when(service).getImageById(1);        mockMvc.perform(get("/getImage/{id}",1).accept(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(jsonPath("$.id", is(1)))
    }

我得到的错误是“未设置内容类型”

这是完整的跟踪:

java.lang.AssertionError: Content type not set
    at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:37)
    at org.springframework.test.util.AssertionErrors.assertTrue(AssertionErrors.java:70)
    at org.springframework.test.util.AssertionErrors.assertNotNull(AssertionErrors.java:106)
    at org.springframework.test.web.servlet.result.ContentResultMatchers.lambda$contentType$0(ContentResultMatchers.java:83)
    at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:196)
    at com.bachelor.ImageControllerTest.testGetImageIdFound(ImageControllerTest.java:61)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:686)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:212)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:208)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:137)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:170)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:154)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:90)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:541)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:763)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:463)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:209)

我错过了什么?

【问题讨论】:

  • 你能把你的导入添加到测试类吗?
  • 我做到了,感谢您的帮助
  • 您需要删除@SpringBootTest JUnit 5 不需要这样做
  • 1) mockMvc.perform(get("/getImage/ 与 getImageById 的完整 URL 不匹配。 2)您没有从该方法返回 img 对象。这样做:return ResponseEntity.of(img); 而不是 return new ResponseEntity&lt;Image&gt;(HttpStatus.OK);
  • 同时确认http://localhost:PORT/project/image/getImage/2在你运行应用程序时正在返回

标签: spring-boot junit mockito junit5


【解决方案1】:

正如我在 cmets 中提到的,我修复了以下问题,现在您的测试通过了:

  • mockMvc.perform(get("/getImage/ 与 getImageById 的完整 URL 不匹配
  • 您没有从该方法返回 img 对象。
  • 确保 Image 类具有 getter,以便正确序列化 JSON

工作代码:

package sotestapp;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.Optional;

@SpringBootApplication
public class TestApp {
    public static void main(String[] args) {
        SpringApplication.run(TestApp.class, args);
    }
}

@RestController
@RequestMapping("/project/image")
class ImageController {
    @Autowired
    ImgService imageService;

    @GetMapping("/getImage/{id}")
    public ResponseEntity<Image> getImageById(@PathVariable Integer id) {
        Optional<Image> img = imageService.getImageById(id);
        return ResponseEntity.of(img);
    }
}

@Service
class ImgService {
    public Optional<Image> getImageById(Integer id) {
        return Optional.of(new Image(1, "test", "test"));
    }
}

class Image {
    int id;
    String path;
    String normal;

    public Image(int id, String path, String normal) {
        this.id = id;
        this.path = path;
        this.normal = normal;
    }

    public int getId() {
        return id;
    }

    public String getPath() {
        return path;
    }

    public String getNormal() {
        return normal;
    }
}

测试:

package sotestapp;

import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;

import java.util.Optional;

import static org.mockito.Mockito.doReturn;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;

@SpringBootTest
@AutoConfigureMockMvc
public class ImageControllerTest {
    @MockBean
    private ImgService service;
    @Autowired
    private MockMvc mockMvc;

    @Test
    void testGetImageIdFound() throws Exception {
        Image mockImage = new Image(1, "mockPath", "Normal");
        doReturn(Optional.of(mockImage)).when(service).getImageById(1);
        mockMvc.perform(get("/project/image/getImage/{id}", 1)
                .accept(MediaType.APPLICATION_JSON_VALUE))
                .andExpect(jsonPath("$.id", Matchers.is(1)));
    }
}

【讨论】:

  • 谢谢,问题确实如你所说。我很感激
【解决方案2】:

你可以试试下面,你不需要@SpringBootTest也加standaloneSetup

@ExtendWith(SpringExtension.class)
@AutoConfigureMockMvc
public class ImageControllerTest {

    @Mock
    private ImgService service;

    @Autowired
    private MockMvc mockMvc;

    @InjectMocks
    private ImageController imageController; 

    @BeforeEach
    public void setup() {

        mockMvc = MockMvcBuilders.standaloneSetup(imageController).build();
    }

    @Test
    @DisplayName("GET /Image/1 - Found")
    void testGetImageIdFound() throws Exception {
        // Setup our mocked service
        Image mockImage = new Image(1, "mockPath", "Normal");
        doReturn(Optional.of(mockImage)).when(service).getImageById(1);

        // Execute the GET request
        mockMvc.perform(get("/getImage/{id}", 1).accept(MediaType.APPLICATION_JSON_UTF8))

                // Validate the response code and content type
                .andExpect(content().contentType(MediaType.APPLICATION_JSON_UTF8))
                .andExpect(header().string(HttpHeaders.LOCATION, "/getImage/1"))
                
                // Validate the returned fields
                .andExpect(jsonPath("$.physicalPath", is("mockPath")))
                .andExpect(jsonPath("$.id", is(1)))
                .andExpect(jsonPath("$.status", is("Normal")));
    }
}

【讨论】:

  • 再次感谢,但这会返回另一个错误:`Caught exception while allowed TestExecutionListener [org.springframework.test.context.support.DependencyInjectionTestExecutionListener@120350eb] to prepare test instance [com.ImageControllerTest@b428830] org .springframework.beans.factory.UnsatisfiedDependencyException:创建名为“com.ImageControllerTest”的bean时出错:通过字段“mockMvc”表示的依赖关系不满足;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException: 预期至少有 1 个符合自动装配候选资格的 bean。
  • 尝试从测试类中删除@AutoConfigureMockMvc
  • 我做了,但它没有帮助:org.springframework.beans.factory.UnsatisfiedDependencyException:创建名称为“com.ImageControllerTest”的bean时出错:通过字段“mockMvc”表示不满足的依赖关系;嵌套异常是 org.springframework.beans.factory.NoSuchBeanDefinitionException:没有“org.springframework.test.web.servlet.MockMvc”类型的合格 bean 可用:预计至少有 1 个有资格作为自动装配候选者的 bean。依赖注解:{@org.springframework.beans.factory.annotation.Autowired(required=true)}
  • 希望你已经添加了答案中提到的@BeforeEach
猜你喜欢
  • 2021-12-17
  • 2023-03-26
  • 2019-08-23
  • 1970-01-01
  • 2017-04-22
  • 2017-06-06
  • 2018-05-25
  • 2021-02-02
  • 2019-10-26
相关资源
最近更新 更多