- Writing Test Cases for Spring hasn't being more fun than ever.
- This was created in order to make writing test cases as easy as writing a controller
- Simple yet powerful Test Case generator
The test cases generated by the script requires the presence of initial java files that handles most of the heavylifting so if your using this script for the first time on a project then consider running this script using --initialData
flag
./spring-Test-Generator.sh tests.json --initialData
-
--no-auth
Upon adding this flag after --initialData it will generate functions that doesn't require OAuth2 authentication. So if your project has no authentication at all, then this flag would be beneficial. If your using JWT or other authentication providers then also use this and write custom token generation function inside generated BaseTest file.
./spring-Test-Generator.sh tests.json --initialData --no-auth
From Spring Boot version 2.2.0 or later. Default spring-boot-starter-test dependency calls for JUnit 5. Which has breaking changes from JUnit 4. If your using such version. Just Update the specific section of the code in your BaseTest file from:
@RunWith(SpringRunner.class)
@WebAppConfiguration
@SpringBootTest(classes = SpringApplication.class)
@Ignore
@ActiveProfiles("unittest")
public abstract class BaseTest {
@Autowired
private WebApplicationContext wac;
protected MockMvc mockMvc;
@ClassRule
public static WireMockClassRule wireMockRule = new WireMockClassRule(8089);
@Rule
public WireMockClassRule instanceRule = wireMockRule;
@Autowired
private FilterChainProxy springSecurityFilterChain;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
.addFilter(springSecurityFilterChain).build();
}
to:
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import com.github.tomakehurst.wiremock.WireMockServer;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options;
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)
@Disabled
public class BaseTest {
@Autowired
private WebApplicationContext wac;
protected MockMvc mockMvc;
protected WireMockServer wireMockRule;
@Autowired
private FilterChainProxy springSecurityFilterChain;
@BeforeEach
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac)
.addFilter(springSecurityFilterChain).build();
this.wireMockRule = new WireMockServer(options()
.port(8089));
}
In Order to use this script without any issues.
At First, we have to install jq
Json Processor for the your Environment using:
sudo apt-get install jq
This is for the Debian and Ubuntu Repositories, check out the below link for the rest of the Linux Distributions, MacOS and Windows:
Then you have to create the tests.json
file or anyother json file present anywhere in this format:
{
"package": "com.spring.project", //Package data of the Main file inside Test Directory
"functions": [
{
"fileName": "SimpleController",
"tests": [
{
"functionName": "getDatafromSpringControllerTest",
"auth": true,
"authData": "default",
"type": "GET",
"endpoint": "/data/2?info=8",
"result": "HttpStatus.OK",
"data": ""
}
]
}
}
For Post/Put/Delete Requests where we have Data:
{
"fileName": "PostDataController",
"tests": [
{
"functionName": "postData",
"auth": true,
"authData": "default",
"type": "Post",
"endpoint": "/sendData",
"result": "HttpStatus.OK",
"data": {
"1": 1,
"2": "2",
"3": true
}
}
]
}
For Multipart File Request we have:
{
"functionName": "multipartSimpleControllerTest",
"auth": false,
"type": "MULTIPART",
"headers": true,
"headersData": [
{
"key": "token",
"value": "generateJWTToken()"
}
],
"fileType": "application/pdf",
"endpoint": "/data/delete?id=3",
"result": "HttpStatus.OK"
}
If you want to use custom email and password apart from the Application Config file authData
key is available and make sure that the auth
key is set to true
by writing your required email<;:semi-colon>password
and entering default
to authData
key would fetch it from ApplicationConfig
values.
"auth": true,
"authData": "mailId;password"
If there is an Endpoint that requires headers:
{
"fileName": "headerController",
"tests": [
{
"functionName": "headerData",
"auth": true,
"authData": "me@mail.com;1234",
"type": "Get",
"headers": true,
"endpoint": "/head",
"result": "HttpStatus.OK",
"data": ""
}
]
}
If in case you have some headers to fill make sure headers
key is set to true
{
"fileName": "NotificationSettingController",
"tests": [
{
"functionName": "notificationSettingUpdateWithExistingResource",
"auth": false,
"type": "POST",
"headers": true,
"headersData": [
{
"key": "directory",
"value": "MED"
},
{
"key": "fileName",
"value": "Medical-2018.pdf"
}
],
"endpoint": "/notificationSettingUpdate",
"result": "HttpStatus.OK",
"data": {
"1": 21,
"2": "40%"
}
}
]
}
In this case the tests.json
file is to be generated a bit differently:
{
"fileName": "AnotherSimpleControllerWithCustomAuth",
"tests": [
{
"functionName": "putSimpleControllerTest",
"auth": false,
"type": "PUT",
"headers": true,
"headersData": [
{
"key": "token",
"value": "generateJWTToken(\"email@mail.com\",\"12345678\")"
},
{
"key": "Accept-Language",
"value": "en"
},
{
"key": "fetchId",
"value": "2"
}
],
"endpoint": "/data/put",
"result": "HttpStatus.OK"
},
{
"functionName": "simpleDeleteControllerTest",
"type": "DELETE",
"headers": true,
"headersData": [
{
"key": "token",
"value": "generateAccessToken()"
}
],
"endpoint": "/data/put",
"result": "HttpStatus.OK"
}
}
}
As you can see in Custom Auth scenario the auth
json key is to be set false or remove the tag all together and custom Token generation function present in BaseTest file is to be passed in the headersData
json key
If your test cases doesn't at all require any authentication then simply:
{
"fileName": "ControllerWithNoAuth",
"tests": [
{
"functionName": "freeAccessControllerTest",
"auth": false,
"type": "PUT",
"endpoint": "/data/put",
"result": "HttpStatus.OK"
}
}
As you can see in No Auth scenario the auth
json key is either set false or removed all together as simple as that.
If your project already has the required initial Data, then simply run:
./spring-Test-Generator.sh <path to the required json file whose test java files needs to be generated>
1) All the necessary functions will be be added in BaseTest
file no special key is needed while invoking script file
2) All it requires that user add mockData
json key to the required functions with some more keys as shown below:
{
"functionName": "mockSimpleGetRequestTest",
"auth": true,
"type": "GET",
"mockData": {
"type": "POST",
"uri": "/mock/uri?data=3",
"responseJson": {
"me": 1
},
"response": "HttpStatus.OK"
},
"headers": true,
"headersData": [
{
"key": "token",
"value": "generateJWTToken(\"email@mail.com\",\"12345678\")"
}
],
"endpoint": "/data/delete?id=3",
"result": "HttpStatus.OK"
}
- if replace key is set to false present at the fileName key then below functions will start to add above the previous functions.
- saving generated test java files at the given directory location
- Creating .bat file for Windows so alternatively you can use git bash to execute bash script in Windows
- result key could be an array or an singular value and subsequent assertions imports required.
- Testing with JUnit 5 code wiremock changes.
Special Thanks to stackoverflow user: @vfalcao
without whom the main component of this script wouldn't have being developed!!