Skip to main content

Spring5 + Rest + Agile (4)

Do more with test:

on the previous practice, we run the embed tomcat to test rest, and we don't need do that since spring provide mock mvc to simplify our test work.
the older code:

/** * The test case used general resttemplate to call api and compare the response. * the whole test is running with an actual tomcat server. */package org.lz.boilerplate.springrest;
import org.junit.Assert;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.boot.test.web.client.TestRestTemplate;import org.springframework.boot.web.server.LocalServerPort;import org.springframework.http.*;import org.springframework.security.oauth2.client.OAuth2RestTemplate;import org.springframework.security.oauth2.client.token.grant.password.ResourceOwnerPasswordResourceDetails;import org.springframework.test.context.junit4.SpringRunner;import org.springframework.util.LinkedMultiValueMap;import org.springframework.util.MultiValueMap;
import java.util.ArrayList;import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class DemoAuthTests {

    public static final String API_DEMO_HELLO = "/api/demo/hello";    public static final String HELLO_API_EXPECTED = "helloworld";    public static final String OAUTH_END_POINT = "/oauth/token";    @LocalServerPort    int randomPort;    @Autowired    private TestRestTemplate restTemplate;
    @Test    public void callHelloApiFailIfNoCredential() {
        ResponseEntity<String> resp = this.restTemplate                .exchange(API_DEMO_HELLO, HttpMethod.GET, null, String.class );        Assert.assertEquals(HttpStatus.UNAUTHORIZED, resp.getStatusCode());    }

    @Test    public void callHelloApiOkWithBasicAuth() {

        ResponseEntity<String> resp = this.restTemplate.withBasicAuth("user", "password")
                .exchange(API_DEMO_HELLO, HttpMethod.GET, null, String.class );        Assert.assertEquals(HttpStatus.OK, resp.getStatusCode());        Assert.assertEquals(HELLO_API_EXPECTED, resp.getBody());    }


    @Test    public void getTokenWithBasicAuth() {
        // $ curl <client-id> : <client-secret>@<api-end-point-url >/oauth/token        // -d grant_type=password -d username=<username> -d password=< password >
        ResponseEntity<String> resp = this.restTemplate.withBasicAuth("lzheng-client", "lzheng-secret")
                .exchange(OAUTH_END_POINT, HttpMethod.POST, getOAuthFormData(), String.class);        Assert.assertEquals(HttpStatus.OK, resp.getStatusCode());        Assert.assertTrue("contain access_token string", resp.getBody().contains("access_token"));    }

    @Test    public void getTokenWithoutBasicAuth() {
        ResponseEntity<String> resp = this.restTemplate.withBasicAuth("", "")

                .exchange(OAUTH_END_POINT, HttpMethod.POST, getOAuthFormData(), String.class );        Assert.assertEquals(HttpStatus.UNAUTHORIZED, resp.getStatusCode());
    }

    @Test    public void callHelooWithOAuth() {
        OAuth2RestTemplate template = restTemplate();
         ResponseEntity<String> resp = template
                .exchange(covertToAbsulateUri(API_DEMO_HELLO), HttpMethod.GET, getOAuthFormData(), String.class );        Assert.assertEquals(HttpStatus.OK, resp.getStatusCode());        Assert.assertEquals(HELLO_API_EXPECTED, resp.getBody());    }

    private String covertToAbsulateUri(String apiDemoHello) {
        return "http://localhost:" + randomPort + apiDemoHello;    }

    private HttpEntity<MultiValueMap<String, String>> getOAuthFormData() {
        MultiValueMap<String, String> map= new LinkedMultiValueMap<>();        map.add("grant_type", "password");        map.add("username", "user");        map.add("password", "password");        HttpHeaders headers = new HttpHeaders();        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        return new HttpEntity<>(map, headers);    }

    private OAuth2RestTemplate restTemplate() {

        ResourceOwnerPasswordResourceDetails resourceDetails = new ResourceOwnerPasswordResourceDetails();        resourceDetails.setGrantType("password");        resourceDetails.setAccessTokenUri(covertToAbsulateUri(OAUTH_END_POINT));
        //-- set the clients info        resourceDetails.setClientId("lzheng-client");        resourceDetails.setClientSecret("lzheng-secret");
        // set scopes        List<String> scopes = new ArrayList<>();        scopes.add("read");        scopes.add("write");        scopes.add("trust");        resourceDetails.setScope(scopes);
        resourceDetails.setUsername("user");        resourceDetails.setPassword("password");
        return new OAuth2RestTemplate(resourceDetails);    }

}

the new code:
package org.lz.boilerplate.springrest;
import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.json.JacksonJsonParser;import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;import org.springframework.boot.test.context.SpringBootTest;import org.springframework.http.MediaType;import org.springframework.test.context.junit4.SpringRunner;import org.springframework.test.web.servlet.MockMvc;import org.springframework.test.web.servlet.ResultActions;import org.springframework.util.LinkedMultiValueMap;import org.springframework.util.MultiValueMap;
import static org.hamcrest.core.StringContains.containsString;import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.httpBasic;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@RunWith(SpringRunner.class)
@SpringBootTest@AutoConfigureMockMvcpublic class MockMvcDemoRestAPITests {
    public static final String API_DEMO_HELLO = "/api/demo/hello";    public static final String OAUTH_END_POINT = "/oauth/token";    public static final String HELLO_API_EXPECTED = "helloworld";    public static final String OAUTH_LZHENG_CLIENT = "lzheng-client";    public static final String OAUTH_LZHENG_SECRET = "lzheng-secret";
    @Autowired    private MockMvc mvc;
    @Test    public void callHelloFailedWithNoCredential() throws Exception {
        this.mvc.perform(get(API_DEMO_HELLO)).andExpect(status().isUnauthorized());    }

    @Test    public void callHelloOkWithBasicAuth() throws Exception {

        this.mvc.perform(get(API_DEMO_HELLO).with(httpBasic("user", "password")))
                .andExpect(status().isOk())
                .andExpect(content().string(HELLO_API_EXPECTED));    }

    @Test    public void getTokenWithBasicAuth() throws Exception {
        this.mvc.perform(post(OAUTH_END_POINT)
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .params(getOAuthFormData())
                .with(httpBasic("lzheng-client", "lzheng-secret")))
                .andExpect(status().isOk())
                .andExpect(content().string(containsString("access_token")));    }

    @Test    public void getTokenWithoutBasicAuth() throws Exception {
        this.mvc.perform(post(OAUTH_END_POINT)
                .with(httpBasic("", "")))
                .andExpect(status().isUnauthorized());    }

    @Test    public void callHelooWithOAuth() throws Exception {
        ResultActions result = this.mvc.perform(post(OAUTH_END_POINT)
                .contentType(MediaType.MULTIPART_FORM_DATA)
                .params(getOAuthFormData())
                .with(httpBasic(OAUTH_LZHENG_CLIENT, OAUTH_LZHENG_SECRET)))
                .andExpect(status().isOk())
                .andExpect(content().string(containsString("access_token")));
        String resultString = result.andReturn().getResponse().getContentAsString();
        JacksonJsonParser jsonParser = new JacksonJsonParser();        String token = jsonParser.parseMap(resultString).get("access_token").toString();
        this.mvc.perform(get(API_DEMO_HELLO)
                .header("Authorization", "Bearer " + token))
                .andExpect(status().isOk())
                .andExpect(content().string(HELLO_API_EXPECTED));    }

    private MultiValueMap<String, String> getOAuthFormData() {
        MultiValueMap<String, String> map = new LinkedMultiValueMap<>();        map.add("grant_type", "password");        map.add("username", "user");        map.add("password", "password");        return map;    }
}

Comments

Popular posts from this blog

How to fix "ValueError when trying to compile python module with VC Express"

When I tried to compile the python, I always get compile issue as following: ------------ ... File "C:\Python26\lib\ distutils\msvc9compiler.py ", line 358, in initialize vc_env = query_vcvarsall(VERSION, plat_spec) File "C:\Python26\lib\ distutils\msvc9compiler.py ", line 274, in query_vcvarsall raise ValueError(str(list(result.keys()))) ValueError: [u'path'] --------------------- Python community discussed a lot but no solution: http://bugs.python.org/issue7511 The root cause is because the latest visual studio change the *.bat file a lot especially on 64bit env. The python 2.7 didn't update the path accordingly. Based on the assumption above, the following solution worked for me. To install Visual Studio 2008 Express Edition with all required components: 1. Install Microsoft Visual Studio 2008 Express Edition. The main Visual Studio 2008 Express installer is available from (the C++ installer name is vcsetup.exe): https://ww...

How to convert the ResultSet to Stream

Java 8 provided the Stream family and easy operation of it. The way of pipeline usage made the code clear and smart. However, ResultSet is still go with very legacy way to process. Per actual ResultSet usage, it is really helpful if converted as Stream. Here is the simple usage of above: StreamUtils.uncheckedConsumer is required to convert the the SQLException to runtimeException to make the Lamda clear.

How to run odoo(openerp8) in IDE from source on windows

1. install python 2.7 (per openerp8's official doc, python 27 is required.) 2. download get-pip.py from https://bootstrap.pypa.io/get-pip.py , execute the command: python get-pip.py 3. get source of openerp8 from https://github.com/odoo/odoo.git 4. execute the command: pip install -r D:\source_code\odoo\openerp8/requirements.txt . (requirements.txt contains all dependencies. ) The pip will install the python module automatically. However, the real world always bring us the issues because our C++ compile environment is not setup correctly.  we will get the link error when pip try to install psycopg2 (driver to access postgresql db.). Go to  http://www.stickpeople.com/projects/python/win-psycopg/  and choose the compiled binary file directly. For Python-ldap, go to  http://www.lfd.uci.edu/~gohlke/pythonlibs/ 5. Finally, go to http://sourceforge.net/projects/pywin32/files/pywin32 and choose correct version for python-win32service. 6. If you are family with...