JUnitTestClassExecuter

JUnitTestClassExecuter

本文介绍了单元测试带弹簧的安全休息控制器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用 spring boot 编写的非常小的 REST 应用程序.

I have a very small REST application written using spring boot.

我想为身份验证编写单元测试,但即使我将 @MockWithUser 添加到测试中,我也会收到 401 错误.

I want to write a unit test for the authentication, but even if i add @MockWithUser to a test, i receive a 401 error.

重要文件是

安全配置

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    auth
            .inMemoryAuthentication()
            .withUser("user").password("password").roles("USER");
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .authorizeRequests()
            .antMatchers("/**")
            .hasRole("USER")
            .anyRequest()
            .permitAll()
            .and()
            .anonymous().disable()
            .exceptionHandling()
            .authenticationEntryPoint(new org.springframework.boot.autoconfigure.security.Http401AuthenticationEntryPoint("headerValue"));
}

带有控制器的 MainApp

The MainApp with a controller

@Controller
@RequestMapping("/test")
@ComponentScan
@SpringBootApplication
public class MainApp {


@RequestMapping(method= RequestMethod.GET)
public @ResponseBody String sample(){

    return "Test";
}

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

最后是测试(不起作用)

And finally the test (which is not working)

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = MainApp.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class AuthenticationTest {

@Autowired
private TestRestTemplate testRestTemplate;

@Autowired
private WebApplicationContext context;

@Autowired
private Filter springSecurityFilterChain;

private MockMvc mvc;

@LocalServerPort
private int port;

@Before
public void setup() {
    mvc = MockMvcBuilders
            .webAppContextSetup(context)
            .addFilters(springSecurityFilterChain)
            .build();
}

@Test
@WithMockUser(username="admin",roles={"USER","ADMIN"})
public void shouldReturn200WhenSendingRequestToControllerWithRoleUser() throws Exception {
    then(SecurityContextHolder.getContext().getAuthentication().isAuthenticated());
    mvc.perform(get("/test")).andExpect(status().isOk());

}

@Test
@WithMockUser(username="admin",roles={"USER","ADMIN"})
public void shouldAuthenticatedBeTrueWithRoleUser() throws Exception {
    then(SecurityContextHolder.getContext().getAuthentication().isAuthenticated());
}
}

如您所见,有两个测试用例.第二个通过,第一个没有(接收 401,而不是 200 作为响应代码,下面的堆栈跟踪).

As you can see, there are two test cases. The second is passed, the first is not (receiving 401, not 200 as response code, stacktrace below).

你能告诉我如何正确测试身份验证吗?

Can you tell me how an can test authentication properly?

java.lang.AssertionError:预期状态:<200> 但是是:<401>在 org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:54)在 org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:81)在 org.springframework.test.web.servlet.result.StatusResultMatchers$10.match(StatusResultMatchers.java:664)在 org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171)在 graphEndpoint.dataConnection.controller.AuthenticationTest.shouldReturn200WhenSendingRequestToControllerWithRoleUser(AuthenticationTest.java:64)在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)在 java.lang.reflect.Method.invoke(Method.java:498)在 org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)在 org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)在 org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)在 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)在 org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)在 org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)在 org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)在 org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)在 org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)在 org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)在 org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)在 org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)在 org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)在 org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)在 org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)在 org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)在 org.junit.runners.ParentRunner.run(ParentRunner.java:363)在 org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)在 org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114)在 org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57)在 org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66)在 org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)在 java.lang.reflect.Method.invoke(Method.java:498)在 org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)在 org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)在 org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32)在 org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)在 com.sun.proxy.$Proxy3.processTestClass(来源不明)在 org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109)在 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)在 sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)在 sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)在 java.lang.reflect.Method.invoke(Method.java:498)在 org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35)在 org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)在 org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:377)在 org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54)在 org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40)在 java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)在 java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)在 java.lang.Thread.run(Thread.java:745)

java.lang.AssertionError: Status expected:<200> but was:<401> at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:54) at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:81) at org.springframework.test.web.servlet.result.StatusResultMatchers$10.match(StatusResultMatchers.java:664) at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:171) at graphEndpoint.dataConnection.controller.AuthenticationTest.shouldReturn200WhenSendingRequestToControllerWithRoleUser(AuthenticationTest.java:64) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75) 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:252) at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) at org.junit.runners.ParentRunner$2.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:191) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.runTestClass(JUnitTestClassExecuter.java:114) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecuter.execute(JUnitTestClassExecuter.java:57) at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassProcessor.processTestClass(JUnitTestClassProcessor.java:66) at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:32) at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93) at com.sun.proxy.$Proxy3.processTestClass(Unknown Source) at org.gradle.api.internal.tasks.testing.worker.TestWorker.processTestClass(TestWorker.java:109) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:35) at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24) at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:377) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:54) at org.gradle.internal.concurrent.StoppableExecutorImpl$1.run(StoppableExecutorImpl.java:40) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) at java.lang.Thread.run(Thread.java:745)

推荐答案

仅使用 addFilters 不足以构建安全上下文.这里有几个解决方案:

Simply using addFilters is not going to be sufficient to build the security context. Here are a couple solutions:

在您的设置方法中替换

.addFilters(springSecurityFilterChain)

.apply(springSecurity())

来自

org.springframework.security.test.web.servlet.setup.SecurityMockMvcConfigurers.springSecurity;

仅此一项就可以解决测试失败问题.这仍然给你留下了一个看起来很糟糕的类,可以使用 WebMvcTest 清理很多.这是使用 WebMvcTest 的更简洁的测试版本.

That alone should resolve the test failures. This still leaves you with a nasty looking class that can be cleaned up quite a lot with the use of WebMvcTest. Here is a more succinct version of your test, using WebMvcTest.

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

@RunWith(SpringRunner.class)
@WebMvcTest(controllers = MainApp.class)
public class AuthenticationTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    @WithMockUser(username = "admin", roles = {"USER", "ADMIN"})
    public void shouldReturn200WhenSendingRequestToControllerWithRoleUser() throws Exception {
        mockMvc.perform(get("/test")).andExpect(status().isOk());
    }
}

这篇关于单元测试带弹簧的安全休息控制器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 21:11