错误:在进行Spring Controller的@WebMvcTest时找不到@SpringBootConfiguration。

62

我正在测试下面给出的控制器

@Controller
public class MasterController {

@GetMapping("/")
public String goLoginPage(){
    return "index";
}
}

我正在按照这个Spring文档来测试我的控制器。 现在,我想通过仅实例化Web层而不是整个Spring上下文来测试我的控制器,就像文档中所述。以下是我编写的代码:

@RunWith(SpringRunner.class)
@WebMvcTest
public class MasterControllerTestWithWebLayer {

@Autowired
MockMvc mockMvc;

@Autowired
MasterController masterController;


@Before
public void setUp() throws Exception {
}

@After
public void tearDown() throws Exception {
}

@Test
public void testLoginHome() throws Exception{
    mockMvc.perform(get("/"))
    .andExpect(status().isOk())
    .andExpect(view().name("index"));
}

}

当我运行这个测试时,我遇到了错误 Unable to find @SpringBootConfiguration,...etc。但我很困惑为什么它要求Spring配置,因为我们不想实例化它,而只想使用Web层。请指导我正确的方向以弄清楚发生了什么,并告诉我如何解决。谢谢。

尝试使用@WebMvcTest(controllers = MasterController.class)。并移除以下代码: @Autowired MasterController masterController; - pvpkiran
@pvpkiran 好的,那样做可以,但为什么不这样呢? - Meena Chaudhary
你的控制器中还有其他依赖项吗?例如像服务类或其他什么东西? - pvpkiran
@pvpkiran 不,而且你猜怎么着,即使我在 @WebMvcTest 中给出控制器名称,它仍然无法工作? - Meena Chaudhary
尝试在MasterControllerTestWithWebLayer类的顶部放置@SpringBootTest(classes = YourSpringBootClassName.class)。 - ProgrammerBoy
5个回答

134
所以这里是解决方案: 有关检测测试配置的文档说:
“搜索算法从包含测试的包向上工作,直到找到一个带有@SpringBootApplication或@SpringBootConfiguration注释的类。只要您以明智的方式构建代码,通常可以找到主配置。”
因此,@SpringBootApplication类应该在包层次结构中较高,例如,如果测试类在包com.zerosolutions.controller中,则@SpringBootApplication类应该在高于com.zerosolutions.controller包的包中,即com.zerosolutions或com。
问题
但是,如果@SpringBootApplication类与测试类处于同一级别,它将无法找到它,即com.zerosolutions.general。在这种情况下,您将收到以下错误消息:
“java.lang.IllegalStateException:无法找到@SpringBootConfiguration,您需要使用@ContextConfiguration或@SpringBootTest(classes = ...)进行测试”
解决方案
如果您正在运行集成测试,可以这样明确提及@SpringBootApplication类。
@RunWith(SpringRunner.class)
@SpringBootTest(classes={SpringBootApp.class})

如果您想要对控制器进行单元测试,您不需要启动整个Spring上下文。相反,您可以用 @WebMvcTest(MasterController.class) 替换 @SpringBootTest。这将只实例化带有 MasterController 的 web 层,而不是整个 Spring 上下文。

问题

但问题是,您又会遇到我们之前面临的错误:

java.lang.IllegalStateException: Unable to find a @SpringBootConfiguration, you need to use @ContextConfiguration or @SpringBootTest(classes=...) with your test

@WebMvtTest 没有像 @SpringBootTest 那样的 classes 属性,可以明确指定 @SpringBootApplication 类。因此,有两种解决方法。

解决方案

第一:将应用程序类移动到高于测试类的包中,即com.zerosolutionscom包中。

第二:明确提及您的 @SpringBootApplication 类,如下所示:

@RunWith(SpringRunner.class)
@WebMvcTest(MasterController.class)
@ContextConfiguration(classes={SpringBootApp.class})

希望这样能消除对Spring测试配置的困惑。谢谢。


你的回答帮助我解决了一个问题,我已经花费数小时来解决它。测试类无法找到主引导应用程序类,尽管它似乎在相同的包中,但在主文件夹和测试文件夹中不同。一旦我使用注释@SpringBootTest(classes=...)明确指定了主应用程序类,事情就开始工作了。 - Kishore
这对我很有帮助。在我的情况下,我的测试是一个Kotlin类,放置在一个没有任何“package”声明的文件中。这是由于一些复制粘贴和移动东西造成的。Intellij的Kotlin插件从未警告我关于错位的类。 - ygor
非常好的答案,直指问题的核心,并帮助我理解了问题和解决方案! - akila
讲解得非常清晰! - X-HuMan

33
如果你的Application.java类(在src/main/java下)位于com.A.B下,那么你的测试类ApplicationTest.java(在src/test/java下)需要位于com.A.B或com.A.B.C或com.A.B.C.D下。如果测试类位于以下包中,则会出现错误:com.A或com.A.C或com.A.D。在Spring Boot中,一般规则是测试类包名需要以要测试的Java类包名的包名开头。请注意保留所有HTML标签。

1
在我的项目中,我的 Application.class 位于 src/main/java/com/company/example,而我的测试类 ApplicationTest.java 位于 src/test/java/com/company/example。测试的执行(mvn test)仍然会抛出 IllegalStateException 异常。我是否误解了您的解释?我以为 Spring Boot 可以通过这种设置自动找到应用程序类。 - Otrebor
1
是的,Spring Boot测试类应该与主类在同一个包中。 - Akash5288

2

检查src/test/java是否与主类包名称相同。 src/test/java/com/example/abc与src/test/java/com/example/abc相同。


1

我遇到了同样的错误,发现当我生成项目时,我的pom.xml中的groupId显示为com.example而不是我的实际域名:


<groupId>com.example</groupId>

我将pom.xml更正为:


<groupId>com.mydomain</groupId>

接下来,我将文件结构从


src/test/java/com/example 更改为 src/test/java/com/mydomain

最后,我必须更新位于我的文件夹内的包声明


SampleProjectApplicationTest.java

以匹配正确的文件结构。 一旦所有这些都就位了,测试就可以正常工作。

我不确定自己为什么会在整个项目中都正确的情况下出现com.example,但在我这种情况下,修复方法就那么简单。

希望这能帮助到其他人。


0
只需将测试包的名称替换为主应用程序类的包名称。
例如:- package com.kotlin.dealerMainApplication 这是我的主要应用程序包名称,因此我将在我的测试包中放置相同的名称。
这对我有用!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接