英文:
Percisely configure spring junit 5 test config
问题
以下是您提供的内容的中文翻译:
使用spring-boot和junit5编写单元测试一直有些困难。
我已经阅读了许多文章以及一些junit5的文档,但没有找到任何有帮助的内容(或者我可能看漏了)。
测试代码:
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = ScoreTestConfiguration.class)
@AutoConfigureMockMvc
public class ScoreControllerTest {
private static final String SCORE_ENDPOINT = "/scoring";
private static final ObjectMapper MAPPER = new ObjectMapper();
@Autowired
private MockMvc mockMvc;
@MockBean
private ScoreService mockScoreService;
@BeforeEach
public void setUp() {
ScoreResponseDto response = getScoreResponseDto();
when(mockScoreService.getScore(any(), any(), any(), any(), any(), any())).thenReturn(response);
}
@NotNull
private ScoreResponseDto getScoreResponseDto() {
ScoreResponseDto response = new ScoreResponseDto();
response.setCid("qwe13423qw");
response.setData(new ScoreResponseDto.ScoringData(0.78f));
return response;
}
@Test
public void sendValidRequest_getResponse_andOkStatus() throws Exception {
String request = SCORE_ENDPOINT +
"/380715346789" + //msisdn
"?score_formula=1234" +
"&clientId=5678" +
"&cid=543" +
"&stateType=" + StateType.ACTIVE.name() +
"&subscriberType=" + SubscriberType.POSTPAID.getValue();
String jsonResponse = MAPPER.writeValueAsString(getScoreResponseDto());
System.out.println("jsonResponse: " + jsonResponse);
mockMvc.perform(get(request))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(jsonResponse));
}
}
配置(这是一个试验,只获取某些类,但我失败了):
@Configuration
@ComponentScan(basePackages = "com.some.path.to.rest")
class ScoreTestConfiguration {
}
在执行测试时,我假设全局上下文已被初始化,尽管我在@Configuration类中指定了仅加载其中的一部分。
我的问题是,如何控制和设置spring-boot和junit5测试的精确测试上下文配置。
实际上,如果有人能提供一些有关如何组织本地测试框架的最佳实践的参考资料,我将非常感激。
提前谢谢!
请注意,我已根据您的要求仅返回了翻译的部分,没有额外的内容。
英文:
Struggling for quite some with writing unit tests with spring-boot and junit5.
I've read lots of articles and some of the junit5 documentation but didn't find anything that would help (or I'm just blind).
test:
@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = ScoreTestConfiguration.class)
@AutoConfigureMockMvc
public class ScoreControllerTest {
private static final String SCORE_ENDPOINT = "/scoring";
private static final ObjectMapper MAPPER = new ObjectMapper();
@Autowired
private MockMvc mockMvc;
@MockBean
private ScoreService mockScoreService;
@BeforeEach
public void setUp() {
ScoreResponseDto response = getScoreResponseDto();
when(mockScoreService.getScore(any(),any(),any(),any(),any(),any())).thenReturn(response);
}
@NotNull
private ScoreResponseDto getScoreResponseDto() {
ScoreResponseDto response = new ScoreResponseDto();
response.setCid("qwe13423qw");
response.setData(new ScoreResponseDto.ScoringData(0.78f));
return response;
}
@Test
public void sendValidRequest_getResponse_andOkStatus() throws Exception {
String request = SCORE_ENDPOINT +
"/380715346789" + //msisdn
"?score_formula=1234" +
"&clientId=5678" +
"&cid=543" +
"&stateType=" + StateType.ACTIVE.name() +
"&subscriberType=" + SubscriberType.POSTPAID.getValue();
String jsonResponse = MAPPER.writeValueAsString(getScoreResponseDto());
System.out.println("jsonResponse: " + jsonResponse);
mockMvc.perform(get(request))
.andDo(print())
.andExpect(status().isOk())
.andExpect(content().string(jsonResponse));
}
}
configuration (it's an experiment to get only certain only certain classes but I failed):
@Configuration
@ComponentScan(basePackages = "com.some.path.to.rest")
class ScoreTestConfiguration {
}
While test execution , I assume, that global context is been initiated despite that I specified to load only part of it in @Configuration class.
My question how can I control and setup precise configuration of test context for spring-boot and junit5 test.
Actually if somebody will give some references about best practices hot to organize local testing framework I'll be really grateful.
Thank you in advance!
答案1
得分: 1
以下是翻译好的内容:
没有看到更多的您的代码,很难确定为什么您的测试配置不满足您的需求。我创建了一个示例项目,其中包含几个类似于您的情况以及其他一些示例 - 您可以在GitHub上找到它。以下是您可以在那里找到的示例列表,附有简短的描述。
@SpringBootTest(classes = TestedController.class)
@AutoConfigureMockMvc
public class TestWithoutConfiguration {
@Test
void fails() {
}
}
这个测试失败了,因为除了控制器bean之外,没有提供任何配置 - 无法找到和注入任何bean。
@SpringBootTest(classes = {TestedController.class, TestConfiguration.class})
@AutoConfigureMockMvc
public class TestWithTestButWithoutMockBeanConfiguration {
@Test
void fails() {
}
}
在这里,我们使用一个测试配置为我们的控制器提供了一个服务bean,但我们仍然缺少该服务使用的bean - MockedUtilInterface
(见下文)。
@SpringBootTest(classes = {TestedController.class, TestConfiguration.class})
@AutoConfigureMockMvc
public class TestWithTestConfiguration {
@Autowired
private MockMvc mockMvc;
@MockBean
private MockedUtilInterface mockedUtil;
@Test
void test() throws Exception {
when(mockedUtil.value())
.thenReturn(100);
mockMvc.perform(get("/test"))
.andExpect(content().string("100 - rest service from component scan value"));
}
}
这个测试通过了 - TestConfiguration提供了服务bean,我们还创建了一个MockedUtilInterface
bean作为模拟。模拟被注入到测试配置指向的服务中,然后将服务注入到实际控制器中。
@SpringBootTest
@AutoConfigureMockMvc
public class TestWithActualConfiguration {
@Autowired
private MockMvc mockMvc;
@Test
void test() throws Exception {
mockMvc.perform(get("/test"))
.andExpect(content().string("0 - not a test value"));
}
}
这个测试也通过了,它使用所有实际配置,不加载测试配置,因此所有bean都是我们实际应用程序的bean(就好像它在容器中运行一样)。
@SpringBootTest
@AutoConfigureMockMvc
public class TestWithInnerTestConfiguration {
@Configuration
@Import(TestedApplication.class)
static class InnerConfiguration {
@Bean
TestedServiceInterface service(MockedUtilInterface mockedUtil) {
return () -> mockedUtil.value() + " - inner value";
}
}
@Autowired
private MockMvc mockMvc;
@MockBean
private MockedUtilInterface mockedUtil;
@Test
void test() throws Exception {
when(mockedUtil.value())
.thenReturn(12345);
mockMvc.perform(get("/test"))
.andExpect(content().string("12345 - inner value"));
}
}
这是一个内部类配置的示例,可以覆盖一些bean,使用一些实际bean,并且还可以使用提供的@MockBeans
。
这里您可以找到为测试配置bean的多种方法。
英文:
Without seeing more of your code, it's hard to tell why your test configuration does not meet your needs. I've created a sample project with a few different examples similar to your case and some other - you can find it here on GitHub. Below is the list of examples you can find there with a short description.
@SpringBootTest(classes = TestedController.class)
@AutoConfigureMockMvc
public class TestWithoutConfiguration {
@Test
void fails() {
}
}
This test fails, since no configuration (apart from the controller bean) is provided - no beans can be found and injected.
@SpringBootTest(classes = {TestedController.class, TestConfiguration.class})
@AutoConfigureMockMvc
public class TestWithTestButWithoutMockBeanConfiguration {
@Test
void fails() {
}
}
Here we use a test configuration that provides a service bean for our controller, but we still lack a bean used by that service - MockedUtilInterface
(see below).
@SpringBootTest(classes = {TestedController.class, TestConfiguration.class})
@AutoConfigureMockMvc
public class TestWithTestConfiguration {
@Autowired
private MockMvc mockMvc;
@MockBean
private MockedUtilInterface mockedUtil;
@Test
void test() throws Exception {
when(mockedUtil.value())
.thenReturn(100);
mockMvc.perform(get("/test"))
.andExpect(content().string("100 - rest service from component scan value"));
}
}
This test passes - TestConfiguration provides the service bean and we're also creating a MockedUtilInterface
bean as a mock. The mock is injected into the service to which the test configuration points and the service is injected into the actual controller.
@SpringBootTest
@AutoConfigureMockMvc
public class TestWithActualConfiguration {
@Autowired
private MockMvc mockMvc;
@Test
void test() throws Exception {
mockMvc.perform(get("/test"))
.andExpect(content().string("0 - not a test value"));
}
}
This test also passes and it uses all the actual configuration, no test configuration is loaded, so all the beans are the beans from our actual application (as if it was run in a container).
@SpringBootTest
@AutoConfigureMockMvc
public class TestWithInnerTestConfiguration {
@Configuration
@Import(TestedApplication.class)
static class InnerConfiguration {
@Bean
TestedServiceInterface service(MockedUtilInterface mockedUtil) {
return () -> mockedUtil.value() + " - inner value";
}
}
@Autowired
private MockMvc mockMvc;
@MockBean
private MockedUtilInterface mockedUtil;
@Test
void test() throws Exception {
when(mockedUtil.value())
.thenReturn(12345);
mockMvc.perform(get("/test"))
.andExpect(content().string("12345 - inner value"));
}
}
And here's an example of an inner class configuration that overrides some beans, uses some actual beans and can also make use of provided @MockBeans
.
Here you can find quite a few ways to configure the beans for a test.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论