Spring-boot WebMvcTest,为什么我在提供模拟的 UserDetailsService 时得到这个 NullPointer?
Spring-boot WebMvcTest, why am i getting this NullPointer when i provide a mocked UserDetailsService?
我正在尝试在 Spring 引导中创建一些 @WebMvcTest
案例。我有一个正在测试的控制器,我正在尝试使用 @WithUserDetails
以便我可以测试作为参数传递给我的控制器方法的 Authentication
对象。
我有一个名为 EmployeeDetails
的自定义 UserDetails
扩展程序。
我用 @MockBean
模拟了我的 UserDetailsService
并使用 given(userDetailsService.loadUserByUsername(anyString())).willReturn(new EmployeeDetails(employee, account));
将其 return 自定义 EmployeeDetails
对象
但是,当我 运行 测试时,出现以下错误:
java.lang.IllegalStateException: Unable to create SecurityContext using @org.springframework.security.test.context.support.WithUserDetails(setupBefore=TEST_METHOD, userDetailsServiceBeanName=userDetailsService, value=someemail@email.com)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createTestSecurityContext(WithSecurityContextTestExecutionListener.java:126)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createTestSecurityContext(WithSecurityContextTestExecutionListener.java:96)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.beforeTestMethod(WithSecurityContextTestExecutionListener.java:62)
at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:289)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=11=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: java.lang.NullPointerException
at org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory.createSecurityContext(WithUserDetailsSecurityContextFactory.java:63)
at org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory.createSecurityContext(WithUserDetailsSecurityContextFactory.java:44)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createTestSecurityContext(WithSecurityContextTestExecutionListener.java:123)
... 23 more
这是什么原因造成的?我不明白。我的印象是模拟的 UserDetailsService
应该 return 我在 given
调用中提供的对象。为什么我得到 NullPointer?谁能指出我正确的方向?
谢谢!
这是我的测试用例:
@RunWith(SpringRunner.class)
@WebMvcTest(PDPController.class)
@AutoConfigureMockMvc(addFilters = false)
public class PDPControllerTests {
@Autowired
private MockMvc mvc;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private PDPService pdpService;
@MockBean(name = "userDetailsService")
private MyUserDetailsService userDetailsService;
//..
@Test
@WithUserDetails(value = "someemail@email.com", userDetailsServiceBeanName = "userDetailsService")
public void testSaveBackground_returns_result_from_service() throws Exception {
PersonalDevelopmentPlan pdp = new PersonalDevelopmentPlan();
pdp.setEmployee(EMPLOYEE_ID);
Account account = new Account();
Employee employee = new Employee();
given(pdpService.saveBackground(eq(EMPLOYEE_ID), any(), anyInt())).willReturn(pdp);
given(userDetailsService.loadUserByUsername(anyString())).willReturn(new EmployeeDetails(employee, account));
mvc.perform(patch(URL_WITH_ID + "/background").secure(true)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(pdp)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.employee", Matchers.is(EMPLOYEE_ID)));
}
}
- 添加以下内容
@PostConstruct
public void setup() {
Account account = new Account();
Employee employee = new Employee();
given(userDetailsService.loadUserByUsername(anyString()))
.willReturn(new EmployeeDetails(employee, account));
}
- 并从测试方法中删除以下行
given(userDetailsService.loadUserByUsername(anyString()))
.willReturn(new EmployeeDetails(employee, account));
我正在尝试在 Spring 引导中创建一些 @WebMvcTest
案例。我有一个正在测试的控制器,我正在尝试使用 @WithUserDetails
以便我可以测试作为参数传递给我的控制器方法的 Authentication
对象。
我有一个名为 EmployeeDetails
的自定义 UserDetails
扩展程序。
我用 @MockBean
模拟了我的 UserDetailsService
并使用 given(userDetailsService.loadUserByUsername(anyString())).willReturn(new EmployeeDetails(employee, account));
EmployeeDetails
对象
但是,当我 运行 测试时,出现以下错误:
java.lang.IllegalStateException: Unable to create SecurityContext using @org.springframework.security.test.context.support.WithUserDetails(setupBefore=TEST_METHOD, userDetailsServiceBeanName=userDetailsService, value=someemail@email.com)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createTestSecurityContext(WithSecurityContextTestExecutionListener.java:126)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createTestSecurityContext(WithSecurityContextTestExecutionListener.java:96)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.beforeTestMethod(WithSecurityContextTestExecutionListener.java:62)
at org.springframework.test.context.TestContextManager.beforeTestMethod(TestContextManager.java:289)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:251)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:97)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access[=11=]0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:190)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:230)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:58)
Caused by: java.lang.NullPointerException
at org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory.createSecurityContext(WithUserDetailsSecurityContextFactory.java:63)
at org.springframework.security.test.context.support.WithUserDetailsSecurityContextFactory.createSecurityContext(WithUserDetailsSecurityContextFactory.java:44)
at org.springframework.security.test.context.support.WithSecurityContextTestExecutionListener.createTestSecurityContext(WithSecurityContextTestExecutionListener.java:123)
... 23 more
这是什么原因造成的?我不明白。我的印象是模拟的 UserDetailsService
应该 return 我在 given
调用中提供的对象。为什么我得到 NullPointer?谁能指出我正确的方向?
谢谢!
这是我的测试用例:
@RunWith(SpringRunner.class)
@WebMvcTest(PDPController.class)
@AutoConfigureMockMvc(addFilters = false)
public class PDPControllerTests {
@Autowired
private MockMvc mvc;
@Autowired
private ObjectMapper objectMapper;
@MockBean
private PDPService pdpService;
@MockBean(name = "userDetailsService")
private MyUserDetailsService userDetailsService;
//..
@Test
@WithUserDetails(value = "someemail@email.com", userDetailsServiceBeanName = "userDetailsService")
public void testSaveBackground_returns_result_from_service() throws Exception {
PersonalDevelopmentPlan pdp = new PersonalDevelopmentPlan();
pdp.setEmployee(EMPLOYEE_ID);
Account account = new Account();
Employee employee = new Employee();
given(pdpService.saveBackground(eq(EMPLOYEE_ID), any(), anyInt())).willReturn(pdp);
given(userDetailsService.loadUserByUsername(anyString())).willReturn(new EmployeeDetails(employee, account));
mvc.perform(patch(URL_WITH_ID + "/background").secure(true)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(pdp)))
.andExpect(status().isOk())
.andExpect(jsonPath("$.employee", Matchers.is(EMPLOYEE_ID)));
}
}
- 添加以下内容
@PostConstruct
public void setup() {
Account account = new Account();
Employee employee = new Employee();
given(userDetailsService.loadUserByUsername(anyString()))
.willReturn(new EmployeeDetails(employee, account));
}
- 并从测试方法中删除以下行
given(userDetailsService.loadUserByUsername(anyString()))
.willReturn(new EmployeeDetails(employee, account));