如何在SpringBootTest中将基本auth添加到Autowired testRestTemplate; Spring Boot 1.4

时间:2016-09-23 01:13:53

标签: spring-mvc spring-security spring-boot spring-test-mvc

我在Spring Boot 1.4之前的OAuth集成测试看起来如下(更新只是为了不使用已弃用的功能):

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { ApplicationConfiguration.class }, webEnvironment = WebEnvironment.RANDOM_PORT)
public class OAuth2IntegrationTest {

    @Value("${local.server.port}")
    private int port;

    private static final String CLIENT_NAME = "client";
    private static final String CLIENT_PASSWORD = "123456";

    @Test
    public void testOAuthAccessTokenIsReturned() {
        MultiValueMap<String, String> request = new LinkedMultiValueMap<String, String>();
        request.set("username", "user");
        request.set("password", password);
        request.set("grant_type", "password");
        @SuppressWarnings("unchecked")
        Map<String, Object> token = new TestRestTemplate(CLIENT_NAME, CLIENT_PASSWORD)
            .postForObject("http://localhost:" + port + "/oauth/token", request, Map.class);
        assertNotNull("Wrong response: " + token, token.get("access_token"));
    }
}

我现在想要使用此处所述的Autowired TestRestTemplate http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-working-with-random-ports

@RunWith(SpringRunner.class)
@SpringBootTest(classes = {
    ApplicationConfiguration.class }, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class OAuth2IntegrationTest {

    private static final String CLIENT_NAME = "client";
    private static final String CLIENT_PASSWORD = "123456";

    @Autowired
    private TestRestTemplate testRestTemplate;

    @Test
    public void testOAuthAccessTokenIsReturned() {
        MultiValueMap<String, String> request = new LinkedMultiValueMap<String, String>();
        request.set("username", "user");
        request.set("password", password);
        request.set("grant_type", "password");
        @SuppressWarnings("unchecked")

        Map<String, Object> token1 = this.testRestTemplate. //how to add basic auth here
        assertNotNull("Wrong response: " + token, token.get("access_token"));
    }
}

我认为这是添加auth的最近方式:

  

Spring 4.0.0 basic authentication with RestTemplate

我想使用Autowired testRestTemplate来避免在我的测试中解析主机和端口。有没有办法做到这一点?

5 个答案:

答案 0 :(得分:11)

这在Spring Boot 1.4.1中得到修复,它有一个额外的方法

  

testRestTemplate.withBasicAuth(用户名,密码)

@Autowired
private TestRestTemplate testRestTemplate;

@Test
public void testOAuthAccessTokenIsReturned() {
    MultiValueMap<String, String> request = new LinkedMultiValueMap<String, String>();
    request.set("username", USERNAME);
    request.set("password", password);
    request.set("grant_type", "password");
    @SuppressWarnings("unchecked")
    Map<String, Object> token = this.testRestTemplate.withBasicAuth(CLIENT_NAME, CLIENT_PASSWORD)
            .postForObject(SyntheticsConstants.OAUTH_ENDPOINT, request, Map.class);
    assertNotNull("Wrong response: " + token, token.get("access_token"));
}

答案 1 :(得分:1)

有一个更好的解决方案,所以你不需要每次都重新输入带有基本的部分

@Autowired
private TestRestTemplate testRestTemplate;

@BeforeClass
public void setup() {
    BasicAuthorizationInterceptor bai = new BasicAuthorizationInterceptor(CLIENT_NAME, CLIENT_PASSWORD);
    testRestTemplate.getRestTemplate().getInterceptors().add(bai);
}

@Test
public void testOAuthAccessTokenIsReturned() {
    MultiValueMap<String, String> request = new LinkedMultiValueMap<String, String>();
    request.set("username", USERNAME);
    request.set("password", password);
    request.set("grant_type", "password");
    @SuppressWarnings("unchecked")
    Map<String, Object> token = this.testRestTemplate.postForObject(SyntheticsConstants.OAUTH_ENDPOINT, request, Map.class);
    assertNotNull("Wrong response: " + token, token.get("access_token"));
}

答案 2 :(得分:0)

虽然the accepted answer是正确的,但就我而言,我必须在每个测试方法和类中复制testRestTemplate.withBasicAuth(...)

所以,我尝试在src/test/java/my.microservice.package中定义一个这样的配置:

@Configuration
@Profile("test")
public class MyMicroserviceConfigurationForTest {

    @Bean
    public TestRestTemplate testRestTemplate(TestRestTemplate testRestTemplate, SecurityProperties securityProperties) {
        return testRestTemplate.withBasicAuth(securityProperties.getUser().getName(), securityProperties.getUser().getPassword());
    }

}

似乎具有覆盖默认TestRestTemplate定义的效果,允许在我的测试类中的任何位置注入凭据感知TestRestTemplate

我不完全确定这是否真的是一个有效的解决方案,但你可以尝试一下......

答案 3 :(得分:0)

如果您仍在应用程序中使用“基本身份验证”,并且在application.properties文件中设置了“ user.name”和“ user.password”属性,那么我认为有更好的解决方案:

public class YourEndpointClassTest {
    private static final Logger logger = LoggerFactory.getLogger(YourEndpointClassTest.class);  

    private static final String BASE_URL = "/your/base/url";

    @TestConfiguration
    static class TestRestTemplateAuthenticationConfiguration {

        @Value("${spring.security.user.name}")
        private String userName;

        @Value("${spring.security.user.password}")
        private String password;

        @Bean
        public RestTemplateBuilder restTemplateBuilder() {
            return new RestTemplateBuilder().basicAuthentication(userName, password);
        }
    }


    @Autowired
    private TestRestTemplate restTemplate;

//here add your tests...

答案 4 :(得分:0)

在单个测试用例中,您可以这样做:

@Test
public void test() {
    ResponseEntity<String> entity = testRestTemplate
            .withBasicAuth("username", "password")
            .postForEntity(xxxx,String.class);
    Assert.assertNotNull(entity.getBody());
}

并为每个测试用例在您的测试类中添加此方法:

@Before
public void before() {
    // because .withBasicAuth() creates a new TestRestTemplate with the same 
    // configuration as the autowired one.
     testRestTemplate = testRestTemplate.withBasicAuth("username", "password");
}