Spring - 如何正确使用@Autowired来防止controller / MockMvc为空?

2024-03-13

我正在尝试运行一些单元测试并遇到一个问题,我确信该问题源于对自动装配的误解。我有一个单元测试类,我正在尝试使用@Autowired在 MockMvc 和 REST 控制器上——两者最终都为 null。

我看到一些消息来源试图解释为什么会发生这种情况(包括这个更多 更少 帖子 https://www.moreofless.co.uk/spring-mvc-java-autowired-component-null-repository-service/和一个乐于助人的StackOverflow 帖子 https://stackoverflow.com/questions/19896870/why-is-my-spring-autowired-field-null这给了我一些见解,但并没有完全帮助我解决我的问题)。

下面是我为重现此问题而制作的示例项目的相关源代码。

ManagerControllerTest.java

@RunWith(SpringRunner.class)
@WebMvcTest(ManagerController.class)
public class ManagerControllerTest {
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private Manager manager;

    @Autowired
    private ManagerController controller;

    @Test
    public void controllerNotNull() throws Exception {
        assertThat(controller).isNotNull();
    }

    @Test
    public void testStoreSomething() throws Exception {
        String path = "/manager/store-something/";

        MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(path)
                    .characterEncoding("UTF-8")
                    .contentType(MediaType.APPLICATION_JSON);

        MvcResult result = mockMvc.perform(builder).andReturn();
        assertEquals(HttpStatus.CREATED, result.getResponse().getStatus());
    }
}

The controllerNotNull()测试结果在

java.lang.AssertionError:期望实际不为空

不过,奇怪的是,当我用 Java 创建一个新的 Gradle 项目并将本文中的示例代码导入其中时,controllerNotNull() passes.

And testStoreSomething()结果是

java.lang.NullPointerException 位于 com.example.sandbox.rest.ManagerControllerTest.testStoreSomething(ManagerControllerTest.java:46)

这里存在一个问题:我误解了什么?我究竟做错了什么?我可以删除@Autowired从控制器并实例化它new ManagerController()但我留下了 MockMvc 问题。

ManagerController.java

@Controller
@RequestMapping(value = "/manager/")
public class ManagerController {
    Manager manager = new Manager(new StringStorage());

    @PostMapping(value = "store-something")
    private ResponseEntity<?> storeSomething(String str) {
        manager.storeSomething(str);
        return new ResponseEntity<>(CREATED);
    }
}

管理器.java

public class Manager {
    private final Storage storage;

    public Manager(Storage storage) {
        this.storage = storage;
    }

    public void storeSomething(String str) {
        storage.store(str);
    }
}

存储.java

public interface Storage {
    void store(String str);
}

字符串存储.java

public class StringStorage implements Storage {
    Map<String, String> stringMap;

    @Override
    public void store(String str) {
        stringMap.put(str, str);
    }
 }

应用程序.java

@SpringBootApplication
public class Application {

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

}

构建.gradle已对原始帖子进行编辑(以使用 JUnit4),但问题仍然存在。

repositories {
    jcenter()
}

apply plugin: 'java'
apply plugin: 'eclipse'

dependencies {
 compile group: 'org.springframework.boot', name: 'spring-boot-starter-web', version: '2.0.0.RELEASE'
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-tomcat', version: '2.0.0.RELEASE'

    testCompile group: 'org.springframework.boot', name: 'spring-boot-starter-test', version: '2.0.0.RELEASE'
    testImplementation 'org.junit.jupiter:junit-jupiter-api:4.0.0'
    testImplementation 'org.junit.jupiter:junit-jupiter-params:4.0.0'
    testCompile group: 'org.mockito', name: 'mockito-core', version: '2.17.0'
    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: "4.0.0"
    testCompile group: 'org.junit.platform', name: 'junit-platform-launcher', version: "1.3.1"
}

@RestController
@RequestMapping(value = "/manager")
public class ManagerController {

    @Autowired
    Manager manager;

    @PostMapping(value = "/store-something")
    private ResponseEntity<?> storeSomething(String str) {
        manager.storeSomething(str);
        return new ResponseEntity<>(CREATED);
    }
}


@Component
public class Manager {

    @Autowired
    private Storage storage;

    public void storeSomething(String str) {
        storage.store(str);
    }
}


public interface Storage {
    void store(String str);
}

@Service
public class StringStorage implements Storage {
    Map<String, String> stringMap = new HashMap<>();

    @Override
    public void store(String str) {
        stringMap.put(str, str);
    }
 }




@SpringBootApplication
public class Application {

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

}

测试类:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class ApplicationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    public void shouldReturnDefaultMessage() throws Exception {
        this.mockMvc.perform(post("/manager/store-something")).andDo(print()).andExpect(status().isOk())
                .andExpect(content().string(containsString("Hello World")));
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Spring - 如何正确使用@Autowired来防止controller / MockMvc为空? 的相关文章

随机推荐

  • 从子视图中的 UIButton 调用 UIViewController 中的方法

    仍在学习 Objective C 并获得正确的结构 我有一个带有 UIViewController 的 iOS 应用程序 它有一个名为 doSomething 的已定义方法 在我的视图控制器中 我有一个视图 并在该视图中以编程方式创建了许多
  • 为什么在使用空引用访问静态时不会出现 NullPointerException? [复制]

    这个问题在这里已经有答案了 在下面的代码中我们得到的值i在空引用上 尽管NPE不在这里 public class Test static int i 10 Test getTest return null public static voi
  • 安装新版本 XCode 15.0 后无法运行应用程序 XCode

    我已经安装了新版本的 Xcode 15 0 此后我无法运行我的 flutter 应用程序 它向我显示以下错误 Error Xcode DT TOOLCHAIN DIR cannot be used to evaluate LIBRARY S
  • 如何矢量化在较大矩阵的子集上运行函数的代码?

    假设我有以下 9 x 5 矩阵 myArray 54 7 8 1 81 7 55 0 22 5 29 6 92 9 79 4 62 2 17 0 74 4 77 5 64 4 58 7 22 7 18 8 48 6 37 8 20 7 43
  • C 中的释放字符串

    如果我写 char a malloc sizeof char 4 a abc char b abc 我是否需要释放该内存 还是由我的系统完成 在您的情况下 您将无法释放动态分配的内存 因为您正在丢失对它的引用 试试这个 include
  • 通过 Android 共享时 Google+ 应用程序显示错误的图片

    我已以编程方式将 Google 共享添加到我的应用程序中 我有一组照片 我将其包含在我的帖子中并使用以下代码共享 private void shareToGooglePlus Launch the Google share dialog w
  • Python-UDP客户端

    我目前正在阅读Pythonbook https www nostarch com blackhatpython并遇到了以下示例 import socket target host 127 0 0 1 target port 80 creat
  • LD_PRELOAD __libc_start_main 的 Makefile

    我想做的事情很简单 当我启动猫鼬服务器时 我想创建一个额外的线程来完成一些额外的工作 为了做到这一点 我想我需要LD PRELOAD the libc start main服务器的 This is spec hooks cpp typede
  • 与邮递员的 CORS

    这个问题已经被问过几次了 但我还是不明白 当我读到有关的答案时 没有 Access Control Allow Origin 标头 问题 它说应该在请求的服务器上设置一个设置以允许跨域 add header Access Control A
  • 适用于 Windows 的 Composer 安装 -

    所以我尝试在我的 Windows 操作系统上安装 Composer 并设置 Laravel 但是当我运行安装时 我不断收到相同的错误 首先 我选择了 php exe 因为它从目录中询问C wamp bin php php5 4 16 我单击
  • JIT 编译的代码驻留在哪里?

    所以我有这个方法 用Java编写 public void myMethod int y int x 5 y doSomething x 并假设我的应用程序多次调用此函数 当在Java虚拟机上运行该方法的编译代码时 JVM将首先解释该方法 然
  • 如何使用 IF EXIST 条件检查目录或文件是否存在?

    如何检查目录或文件是否存在IF EXIST健康 状况 Such as If exist C Windows OR C Windows2 rem Do something else rem Something else 我该怎么做 简单例子1
  • 应该在带花括号的 return 语句中调用哪个构造函数?

    考虑以下代码 struct NonMovable NonMovable default NonMovable const NonMovable default NonMovable NonMovable delete NonMovable
  • 调度程序 BeginInvoke 语法

    我一直在尝试遵循一些 WCF 数据服务示例并具有以下代码 private void OnSaveCompleted IAsyncResult result Dispatcher BeginInvoke gt context EndSaveC

  • 元素可以有结束标签吗?

    我的同事并不真正了解或理解 html 她的工作是向 CMS 输入信息 我注意到她一直关闭她 hr 像这样的标签 hr 我有谷歌 但我找不到任何地方说这是不允许的或可能会导致问题 我知道它应该是 hr 但值得我告诉她还是这是不必要但有效的标记
  • Apollo重新获取不重新渲染组件

    我正在使用 graphql 从网络服务获取数据 我的客户端代码是这样的 import React Component from react import Platform StyleSheet Text ActivityIndicator
  • React - 加载外部脚本的问题

    我正在从事我的第一个 React 项目 并且对 JS 有点陌生 我正在努力解决一个非常基本的问题 我想知道调试这个的最佳实践是什么 我确实创建了我的应用程序create react app我没有成功加载外部脚本 令人惊讶的是 到目前为止 我
  • Aiohttp、Asyncio:运行时错误:事件循环已关闭

    我有两个脚本 scraper py 和 db control py 在 scraper py 我有这样的东西 def scrape category field pages search use proxy proxy file loop
  • JavaScript YUI3 使用全局变量?

    我不知道如何从 YUI3 中更新全局变量 考虑以下代码 window myVariable data one var yuiWrap YUI use node function Y console log window myVariable
  • Spring - 如何正确使用@Autowired来防止controller / MockMvc为空?

    我正在尝试运行一些单元测试并遇到一个问题 我确信该问题源于对自动装配的误解 我有一个单元测试类 我正在尝试使用 Autowired在 MockMvc 和 REST 控制器上 两者最终都为 null 我看到一些消息来源试图解释为什么会发生这种