geek的技术日志,记录每一次技术思考的闪光点。

Spring boot整合Junit测试对于Spring security权限的验证配置

Spring boot里用Junit来测试配置了Spring security权限的restful接口,需要添加两个主要的包。

<!– Test Spring Boot –>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!– Testing security –>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>

一个基本的testcase写法如下

package com.test;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.servlet.HandlerInterceptor;

/**
 * 单元测试
 */
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.MOCK)
public class ExportTests {
   /**
    * 模拟mvc测试对象
    */
   private MockMvc mockMvc;// 2

   /**
    * web项目上下文
    */
   @Autowired
   private WebApplicationContext webApplicationContext; // 3
   /**
    * 所有测试方法执行之前执行该方法
    */
   @Before
   public void before() {
      //获取mockmvc对象实例
      mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build(); // 4
   }

   /**
    * 测试信息导出
    * @throws Exception
    */
   @Test
   @WithMockUser(authorities = {"real-name", "custom-menu"})
   public void testExportRealName() throws Exception
   {
      MvcResult mvcResult = mockMvc
            .perform(
                  MockMvcRequestBuilders.get("/certification/export")
                  .param("realIds","46,47")
            )
            .andReturn();

      //输出经历的拦截器
      HandlerInterceptor[] interceptors = mvcResult.getInterceptors();
      System.out.println(interceptors[0].getClass().getName());

      int status = mvcResult.getResponse().getStatus();
      String responseString = mvcResult.getResponse().getContentAsString();
      System.out.println("返回内容:"+responseString);
      Assert.assertEquals("return status not equals 200", 200, status);
      Assert.assertTrue(responseString.contains("ID,端口号,实名名称,状态,申请时间"));
   }
}

代码里涉及到权限的关键注解是:

@WithMockUser(authorities = {"real-name", "custom-menu"})

该注解对应restful接口里配置的权限是

@RequestMapping(value = "/certification/export", method = RequestMethod.GET)
@PreAuthorize("hasAuthority('real-name')")

如果代码里是使用下面这种hasrole的方式配置权限的

@PreAuthorize("hasRole('ADMIN')")
public void methodTwo(String msg);

那么我们的testcase的注解写法应该如下:

@Test
@WithMockUser(roles={"ADMIN"})
public void testTwo() {
    userService.methodTwo("This is Admin");
}

如果要测试 @PostAuthorize 这种注解方式配置的权限.

@PostAuthorize ("returnObject.userName == authentication.name")
public User methodFour();

那么我们的测试代码里需要使用下面这种注解写法:

@Test
@WithMockUser(username = "ram")
public void testFour1() {
    userService.methodFour();
}

如果你在接口里使用下面这种方式配置了权限

@RequestMapping(value = "/schedule", method = RequestMethod.POST)
@PreAuthorize("#oauth2.hasScope('dataLicense')")
public int schedule() {
    return 0;
}

那么你需要在testcase这样写

@Test
    @WithMockOAuth2Scope(scope = "dataLicense")
    public void testSchedule() throws Exception {
        mockMvc.perform(post("/schedule").contentType(MediaType.APPLICATION_JSON_UTF8).content(json)).andDo(print());
    }

如果你在restful接口如下配置了权限:

 @PreAuthorize("#oauth2.hasScope('myapi:write')")
    @PatchMapping(consumes = APPLICATION_JSON_UTF8_VALUE, produces = APPLICATION_JSON_UTF8_VALUE)
    public Booking patchBooking(OAuth2Authentication authentication, @RequestBody @Valid Booking booking) {
        String subjectId = MyOAuth2Helper.subjectId(authentication);
        booking.setSubjectId(subjectId);
        return bookingRepository.save(booking);
    }

那么你的testcase需要这么写:

@Test
    @WithOAuthSubject(scopes = {"myapi:read", "myapi:write"})
    public void mustHaveValidBookingForPatch() throws Exception {
        mvc.perform(patch(API_URL)
            .header(AUTHORIZATION, "Bearer foo")
            .content(json.write(new Booking("myguid", "aes")).getJson())
            .contentType(MediaType.APPLICATION_JSON_UTF8)
        ).andExpect(status().is2xxSuccessful());
    }
打赏作者

未经允许不得转载:极客技术 » Spring boot整合Junit测试对于Spring security权限的验证配置

分享到:更多 ()

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址