我正在将 Spring Boot 从 1.3 升级到 1.5。为了升级到 1.5 我已经更换了
@SpringApplicationConfiguration(classes = TestConfig.class)
@WebIntegrationTest
和
@SpringBootTest(classes = TestConfig.class)
另外,我正在使用
@Value("${local.server.port}")
protected int port;
获取application.properties文件中定义的端口号。我进一步使用这个端口号来构建一个 REST URL。
但是升级后我收到以下错误,而1.3Spring Boot Test也可以正常工作。
引起:java.lang.IllegalArgumentException:无法在 org.springframework.util.PropertyPlaceholderHelper.parseStringValue(PropertyPlaceholderHelper.java:174) 处解析值“${local.server.port}”中的占位符“local.server.port”
我是否错过了为此工作所需的任何更改。
我正在测试一个控制器:
@RestController()
public class MessagesController {
...
}
Run Code Online (Sandbox Code Playgroud)
使用@WebMvcTest 注释:
@RunWith(SpringRunner.class)
@WebMvcTest(value = {MessagesController.class})
public class MessagesControllerTest {
private MockMvc mvc;
....
this.mvc.perform(
get("/messages/{id}", "dummyId")
.contentType(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk());
...
Run Code Online (Sandbox Code Playgroud)
但是当我启动我的测试时,Spring 尝试序列化一个 List> 类型的对象,但它失败了:
Resolved Exception:
Type = org.springframework.http.converter.HttpMessageNotWritableException
ModelAndView:
View name = null
View = null
Model = null
FlashMap:
Attributes = null
MockHttpServletResponse:
Status = 500
Error message = null
Headers = {Content-Type=[application/json;charset=UTF-8]}
Content type = application/json;charset=UTF-8
Body =
Forwarded URL = null
Redirected URL = null
Cookies = …Run Code Online (Sandbox Code Playgroud) 我正在创建带有@WebMvcTest注释的测试,发现如果我@ComponentScan在应用程序类中有注释,它将破坏测试的预期行为。
根据WebMvcTestjavadoc:
使用此批注将全面禁用自动配置,而是只适用于相关的测试MVC(即配置
@Controller,@ControllerAdvice,@JsonComponent Filter,WebMvcConfigurer和HandlerMethodArgumentResolver咖啡豆,但没有@Component,@Service或@Repository豆类)“。
问题是@ComponentScan它正在实例化用@Service. 如果不是@ComponentScan我在@SpringBootApplication注释中指定扫描基础包,一切都按预期工作。
当我在@WebMvcTest注释中指定控制器类时会发生另一个问题。当@ComponentScan应用程序类中有注释时,它将加载所有控制器,而不是仅加载指定的控制器。
这是 Spring Boot 中的错误吗?
我想使用@ComponentScan是因为注释中excludeFilters没有的属性@SpringBootApplication。
我发现的一种解决方法是创建一个带有@Configuration注释的单独类并将其移动到@ComponentScan那里。
我试图@SpringBootTest在“干净”的上下文中运行 a 而无需MyApplicationContextInitializer执行。
包含在文件MyApplicationContextInitializer内的依赖项spring.factories中,compile-scope如下所示:
org.springframework.context.ApplicationContextInitializer=\
com.eremic.myapp.MyApplicationContextInitializer
Run Code Online (Sandbox Code Playgroud)
测试类:
@SpringBootTest(webEnvironment = RANDOM_PORT)
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = TestContext.class)
public class UsersControllerTest {}
Run Code Online (Sandbox Code Playgroud)
测试配置:
@SpringBootConfiguration
public class TestContext {}
Run Code Online (Sandbox Code Playgroud)
有办法排除MyApplicationContextInitializer吗@SpringBootTest?
我已经厌倦了 exceptFilters @ComponentScan.Filters,但它对 ApplicationContextInitializer 没有影响。
另外,我尝试使用和/或使用TestContext注释@SpringBootApplication和限制组件扫描,但它也没有效果。scanBasePackagesexclude = MyApplicationContextInitializer.class
到目前为止,防止MyApplicationContextInitializer在内部执行的唯一方法@SpringBootTest是删除MyApplicationContextInitializer声明的 Maven 依赖项。
默认情况下@DataJpaTest扫描所有 jpa 存储库和@Entity. 就我而言,我有 5 个存储库包和 5 个实体包。例如
com.acme.product.entity与 相关联 与
com.acme.product.repository
com.acme.users.entity相关联 与
com.acme.users.repository
com.acme.client.entity相关联
com.acme.client.repository
等等....
我想在单独的课程中测试每个部分。例如
@RunWith(SpringRunner.class)
@DataJpaTest
//Some configurations to import only product repositories and product entities
public class TestProductRepository {
@Autowired
TestEntityManager entityManager;
}
Run Code Online (Sandbox Code Playgroud)
请注意,我已经配置了 5 个不同的,EntityManager我想导入它们并使用例如productEntityManagerin 中的TestProductRepository而不是TestEntityManager加载所有存储库/实体的默认值。
多谢
before 和 after 方法在 JUnitPlatform 中不起作用。
代码如下。
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.suite.api.SelectClasses;
import org.junit.runner.RunWith;
@RunWith(JUnitPlatform.class)
@SelectClasses({
MyControllerTest.class
})
public class AdminAppTest {
@BeforeAll
public static void setUp() {
System.out.println("setting up");
}
@AfterAll
public static void tearDown() {
System.out.println("tearing down");
}
}
Run Code Online (Sandbox Code Playgroud)
我只想在方法之前和之后运行。
谢谢
junit integration-testing spring-boot spring-boot-test junit-jupiter
我正在开发一个 Spring Boot 应用程序并编写一些 junit 测试。
但是我发现当我运行任何测试时,tomcat也会启动,这使得这些测试非常慢并且浪费了很多时间。
当我开发SpringMvc应用程序时,junit测试可以在不启动tomcat的情况下运行,它节省了很多时间。
所以,我想问一下是否可以在不启动tomcat的情况下运行springboot测试?
我英语不好。敬请谅解。
我知道。使用@SpringBootTest()Annotation来加载整个Bean显然被认为是一个“ Integration Test.”
然而,使用@SpringBootTest(classes=mybean.class)被认为是“单元测试”,因为它只运行某个(选定的)“”,Bean(Class)尽管它运行了一个 spring。
我还以为使用@ContextConfiguration的方式也是“ Unit Tests.”,因为我以为只有某些类可以被执行,比如@ContextConfusion(classes=myBean.class).
但这是我的错误。我收到了上次 StackOverflow 的答复。
Spring Boot 单元测试中的@SpringBootTest、@ContextConfiguration、@Import
我的最后一个问题--> using 是否@ContextConfiguration可以是“单元测试”$$$answer ---> 不,不能,它是一个在 Spring 中仅运行一个类的集成测试。通常,我们不会只使用 Spring 框架运行一个类。如果只想测试一个类(一个单元)的代码,那么在 spring 容器内运行它有什么好处?是的,在某些情况下,它可以是几个类,但不是数十个或数百个。如果你用 spring 运行一个类,那么在任何情况下,你都必须模拟它的所有依赖项,同样可以用 mockito 来完成......
所以我再问一次。
也是 ” @WebMvcTest” Integration Tests?我以为“ @WebMvcTest”就是“” Unit Test。但是,根据最后一个答案,@WebMvcTest也有春季运行。所以最后一个答案的逻辑是“ @WebMvcTest”也是“ Integration Test,”,但我还是不明白。
我很困惑。我只是在玩文字游戏吗?
@WebMvcTest“ Integration Test”吗?我有一个SpringBootTest测试应该依赖一个单独的类来设置嵌入式 Postgres 和数据源。
因此 Repository 配置如下所示:
package com.stream.repository.configuration
@Configuration
@ComponentScan(basePackages = arrayOf("com.stream.repository"))
@EntityScan(basePackages = arrayOf("com.stream.repository"))
@EnableJpaRepositories(basePackages = arrayOf("com.stream.repository"))
@EnableAutoConfiguration
class RepositoryConfiguration {
Run Code Online (Sandbox Code Playgroud)
测试类如下所示:
package com.stream.webapp.rest
@AutoConfigureMockMvc(addFilters = false)
@SpringBootTest(properties =
[
"spring.jpa.hibernate.ddl-auto=validate",
"spring.jpa.show-sql=true",
"spring.liquibase.enabled=true",
"spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.yml",
"spring.jpa.properties.hibernate.jdbc.time_zone=UTC"
],
classes = [RepositoryConfiguration::class, AuditController::class],
webEnvironment = SpringBootTest.WebEnvironment.MOCK)
class AuditControllerTest {
Run Code Online (Sandbox Code Playgroud)
这就是它变得奇怪的地方。如果我使用该配置运行,它会抱怨找不到EntityManagerFactory
AuditService 需要一个无法找到的类型为“javax.persistence.EntityManagerFactory”的 bean。
经过一番折腾,我找到了解决这个问题的办法。如果我移动它RepositoryConfiguration以便它在包中com.stream.webapp.rest,即与AuditControllerTest它一样神奇地工作。
我似乎找不到任何理由说明为什么会这样。那么任何人都可以解释它并且有办法解决它吗?因为我不想动它。把它放在哪里很有意义。
作为旁注,它是用 Kotlin 编写的,但我不明白为什么在这种情况下它很重要。而这仅用于测试。在测试范围之外运行应用程序时,它可以工作
我还可以补充一点,AuditControllerTest它在一个模块中,RepositoryConfiguration在另一个模块中。如果将其放置在“正确”的包中(仍然是单独的模块),则不确定它是否相关,因为它可以工作
问题的 TL; DR:为什么 spring 关心 …
根据 spring 文档,诸如 之类的字符串属性值10s将被正确转换为java.time.Duration.
事实上,这对我来说适用于主要的应用程序属性。但它在单元测试中失败了。
单元测试
@ExtendWith(SpringExtension.class)
@EnableConfigurationProperties(value = MyConfig.class)
@TestPropertySource("classpath:test.properties")
public class MyUnitTest {
@Autowired
MyConfig config;
...
}
Run Code Online (Sandbox Code Playgroud)
配置类
@ConfigurationProperties(prefix = "my")
@Component
public class MyConfig {
@Value("${my.failed-duration}")
public Duration myDuration;
...
}
Run Code Online (Sandbox Code Playgroud)
测试.属性
my.failed-duration=10s
Run Code Online (Sandbox Code Playgroud)
例外
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:124)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
at org.springframework.test.context.TestContextManager.prepareTestInstance(TestContextManager.java:244)
at org.springframework.test.context.junit.jupiter.SpringExtension.postProcessTestInstance(SpringExtension.java:138)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$6(ClassBasedTestDescriptor.java:350)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.executeAndMaskThrowable(ClassBasedTestDescriptor.java:355)
at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.lambda$invokeTestInstancePostProcessors$7(ClassBasedTestDescriptor.java:350)
at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
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)
at java.base/java.util.stream.Streams$ConcatSpliterator.forEachRemaining(Streams.java:735) …Run Code Online (Sandbox Code Playgroud) spring-boot ×10
spring-boot-test ×10
java ×3
spring ×3
junit ×1
kotlin ×1
spring-data ×1
spring-mvc ×1
tdd ×1
testing ×1