Error while testing: found multiple declaration of #BootstrapWith for test class - rest

I would like to test my CRUD REST Controller for the first time. I have watched some videos and come up with this idea but I am getting error. I am using JPA with mySql. ITodoService is simple interface with CRUD methods. My rest Controller is working when I test it via Postman, so code there is ok.
If you could give me some feedback what might be wrong and where can I check for good imformation about testing REST app because I have spent like 3 hrs without any success :)
#SpringBootTest
#RunWith(SpringRunner.class)
#WebMvcTest
public class TodoFinalApplicationTests {
#Autowired
private MockMvc mockMvc;
#MockBean
private ITodosService iTodosService;
#Test
public void getAllTodosTest() throws Exception {
Mockito.when(iTodosService.findAll()).thenReturn(
Collections.emptyList()
);
MvcResult mvcResult = mockMvc.perform(
MockMvcRequestBuilders.get("/todos")
.accept(MediaType.APPLICATION_JSON)
).andReturn();
System.out.println(mvcResult.getResponse());
Mockito.verify(iTodosService.findAll());
}
}
Error message:
java.lang.IllegalStateException: Configuration error: found multiple declarations of #BootstrapWith for test class [com.damian.todo_Final.TodoFinalApplicationTests]: [#org.springframework.test.context.BootstrapWith(value=class org.springframework.boot.test.context.SpringBootTestContextBootstrapper), #org.springframework.test.context.BootstrapWith(value=class org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTestContextBootstrapper)]
EDIT:
This is code for whole CRUD REST Test
#RunWith(SpringRunner.class)
#AutoConfigureMockMvc
#SpringBootTest(classes = TodoFinalApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
// #WebMvcTest
public class TodoFinalApplicationTests {
#Autowired
private TestRestTemplate restTemplate;
#LocalServerPort
private int port;
private String getRootUrl() {
return "http://localhost:" + port;
}
#Test
public void contextLoads() {
}
#Test
public void getAllTodos() {
HttpHeaders headers = new HttpHeaders();
HttpEntity<String> entity = new HttpEntity<String>(null, headers);
ResponseEntity<String> response = restTemplate.exchange(getRootUrl() + "/employees",
HttpMethod.GET, entity, String.class);
assertNotNull(response.getBody());
}
#Test
public void createNewTodo() {
Todos todo = new Todos();
todo.setId(5);
todo.setTaskDate("15.01.1990");
todo.setTaskStatus(true);
todo.setTaskDescritpion("Description for testing");
ResponseEntity<Todos> postResponse = restTemplate.postForEntity(getRootUrl() + "/todos", todo, Todos.class);
assertNotNull(postResponse);
assertNotNull(postResponse.getBody());
}
#Test
public void testUpdateTodo() {
int id = 1;
Todos todo = restTemplate.getForObject(getRootUrl() + "/todos/" + id, Todos.class);
todo.setTaskDate("15.01.1990");
todo.setTaskStatus(true);
todo.setTaskDescritpion("Updating");
restTemplate.put(getRootUrl() + "/todos/" + id, todo);
Todos updatedTodo = restTemplate.getForObject(getRootUrl() + "/todos/" + id, Todos.class);
assertNotNull(updatedTodo);
}
#Test
public void testDeletedTodo() {
int id = 3;
Todos todo = restTemplate.getForObject(getRootUrl() + "/todos/" + id, Todos.class);
assertNotNull(todo);
restTemplate.delete(getRootUrl() + "/todos/" + id);
try {
todo = restTemplate.getForObject(getRootUrl() + "/todos/" + id, Todos.class);
} catch (final HttpClientErrorException e) {
assertEquals(e.getStatusCode(), HttpStatus.NOT_FOUND);
}
}

You have both #SpringBootTest and #WebMvcTest on one test class. Both classes, among others, specify only what beans should be instantiated in the test context.
The definitions are conflicting, so only one is allowed.
Decide if you want to test:
entire application context - use #SpringBootTest
only controllers - use #WebMvcTest
In your case, I would:
remove #SpringBootTest
specify Controller you want to test in #WebMvcTest
Alternatively, you can
remove #WebMvTest
add AutoConfigureWebMvc
#SpringBootTest brings all beans into context, and thus #WebMvcTest will likely result in a faster test.

Related

JPA. Update dml doesn't work with #Transactional annotation

I tryng to perform an an unpdate within a UnitTest method with org.springframework.transaction.annotation.Transactional annotation, but it seems that the update doesn't work.
If I remove #Transactional annotation on the method, the update works succesfully but it is visible for all others tests too.
Could you please indicate to me where I'm wrong?
I need the update effective only within the method with the #Transactional annotation and not visible for all others methods.
I'm using
Srping boot v 2.6.6. to start the application. I use JPA and Oracle Data Base.
This is my repository class where I use native query.
#Repository
#Transactional
public interface EsercentiRepository extends JpaRepository<EsercentiEntity, Long> {
// Update
#Modifying
#Query(value="update esercenti set sslfl=:sslfl where id_conv=:idConv", nativeQuery=true)
public void updateSslFlagByIdViaQuery(#Param("idConv") long idConv, #Param("sslfl") String sslfl);
// select
#Query(value="select id_conv,c_code,vendor_id,pos_id,abi_code,funzioni,ds,pos_id_sia,rifmer3d,sslfl "
+ " from esercenti where id_conv=:idConv", nativeQuery=true)
public EsercentiEntity getEsercentiByIdConvViaQuery(#Param("idConv") long idConv);
}
This is my Service class.
#Service
#Transactional
public class EsercentiServices implements IEsercenti {
#Autowired
private EsercentiRepository esercentiRepository;
#Override
public void updateSslFlagByIdViaQuery(long idConv, String sslfl) throws Exception {
esercentiRepository.updateSslFlagByIdViaQuery(idConv, sslfl);
}
#Override
public EsercentiEntity getEsercentiByIdConvViaQuery(long idConv) throws Exception {
return esercentiRepository.getEsercentiByIdConvViaQuery(idConv);
}
}
And this is my SpringBootTest class located in the 'test' directory where I use Junit 5 to perform Functional tests.
#EnableTransactionManagement
#TestInstance(TestInstance.Lifecycle.PER_CLASS)
#TestMethodOrder(MethodOrderer.OrderAnnotation.class)
#ExtendWith(SpringExtension.class)
#SpringBootTest
class TestGpay extends BaseServiceTester {
#Autowired
private IEsercenti esercentiServices;
[..]
#Test
#Transactional
public void TestDirectAuthGpayWithPayload(TestInfo testInfo) {
try {
// [..... Some codes]
EsercentiEntity ese = esercentiServices.getEsercentiByIdConvViaQuery(7826L);
esercentiServices.updateSslFlagByIdViaQuery(7826L, "Y");
EsercentiEntity ese2 = esercentiServices.getEsercentiByIdConvViaQuery(7826L);
// Send the http request. I expect to find the data changed on DB as per above update, but it is not.
WebUtils.HttpResponse response = netsJsonClient(endPoint, "POST", jsonObjectRequest.toString(), merId, merIdKsig);
// If I cancel the #Transactoinal annotation on the method level, the update is ok,
// but it is a global update and not only related to this database session.
} catch (Exception e) {
e.printStackTrace();
closeDriver(driver);
fail("Exception on test case " + testInfo.getDisplayName() + " Full Error:" + e);
}
}
Thanks in advance.

Spring Contract does not reach method #Before on base class

I have a single spring contract test:
public class ContractVerifierTest extends BaseClassForIntegrationTests {
#Test
public void validate_shouldSayHello() throws Exception {
// given:
RequestSpecification request = given()
.header("Content-Type", "application/json");
// when:
Response response = given().spec(request)
.get("/sayhello/Eduardo");
// then:
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.header("Content-Type")).matches("application/json.*");
// and:
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).field("['msg']").isEqualTo("hello Eduardo");
}
}
My base class looks like:
#RunWith(SpringRunner.class)
#SpringBootTest(classes = DemoApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
#Slf4j
public class BaseClassForIntegrationTests {
#Value("${app.url}") private String url;
#Value("${app.port}") private int port;
#Before
public void setup() {
log.error("Running setup with url:" + url + ":" + port);
RestAssured.baseURI = url;
RestAssured.port = port;
}
}
The setup method is never reached, funny thing, if I change the annotation to #BeforeEach or #BeforeAll it works as expected.
I have a sample of the project here
With Contract 3.0.x the default testing framework is junit5 you need to Configure the plugin explicitly to use junit 4

How to extract path variable from responseentity in Junit testing

Searched but unfortunately I do not get similar questions. I've pasted my involved codes. It uses Spring DATA framework.
Entity EscalationPolicy with ID automatically generated
controller to hand POST request to create an new policy
update JUnit Test
What I'm trying to do in the test is that first create one new EscalationPolicy with the object set by initTest(). Then fetch and update it. However the ID is unknown and I suppose I need to extract it from the return URI. I don't know how to do it after Mockmvc perform and appreciate any help. Thanks!
#Entity
#Table(name = "T_ESCALATIONPOLICY")
#Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class EscalationPolicy implements Serializable {
#Id
#GeneratedValue(generator = "uuid")
#GenericGenerator(name = "uuid", strategy = "uuid")
private String id;
#Column(name = "policy_name")
private String policy_name;
...
}
#RestController
#RequestMapping("/api")
public class EscalationPolicyResource {
...
/**
* POST /escalationPolicys -> Create a new escalationPolicy.
*/
#RequestMapping(value = "/escalationPolicys",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<Void> create(#RequestBody EscalationPolicy escalationPolicy) throws URISyntaxException {
log.debug("REST request to save EscalationPolicy : {}", escalationPolicy);
if (escalationPolicy.getId() != null) {
return ResponseEntity.badRequest().header("Failure", "A new escalationPolicy cannot already have an ID").build();
}
escalationPolicyRepository.saveAndFlush(escalationPolicy);
return ResponseEntity.created(new URI("/api/escalationPolicys/" + escalationPolicy.getId())).build();
}
...
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest
public class EscalationPolicyResourceTest {
#Before
public void initTest() {
escalationPolicy = new EscalationPolicy();
escalationPolicy.setPolicy_name("Policy Test");
...
}
#Test
#Transactional
public void updatePolicy() throws Exception {
// Create the EscalationPolicy
restEscalationPolicyMockMvc.perform(post("/api/escalationPolicys")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(escalationPolicy)))
.andExpect(status().isCreated());
// Get the created policy
EscalationPolicy e = escalationPolicyRepository.findOne(id);
~~need ID here
}
...
}
Though it may not be the most elegant way to deal with it, I think a way to bypass the problem. I save the id in the header map and in the test code to extract it.
#RestController
#RequestMapping("/api")
public class EscalationPolicyResource {
...
/**
* POST /escalationPolicys -> Create a new escalationPolicy.
*/
#RequestMapping(value = "/escalationPolicys",
method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE)
#Timed
public ResponseEntity<Void> create(#RequestBody EscalationPolicy escalationPolicy) throws URISyntaxException {
log.debug("REST request to save EscalationPolicy : {}", escalationPolicy);
if (escalationPolicy.getId() != null) {
return ResponseEntity.badRequest().header("Failure", "A new escalationPolicy cannot already have an ID").build();
}
escalationPolicyRepository.saveAndFlush(escalationPolicy);
HttpHeaders headers = new HttpHeaders();
headers.set("policyID", escalationPolicy.getId());
return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
}
...
}
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
#IntegrationTest
public class EscalationPolicyResourceTest {
#Before
public void initTest() {
escalationPolicy = new EscalationPolicy();
escalationPolicy.setPolicy_name("Policy Test");
...
}
#Test
#Transactional
public void updatePolicy() throws Exception {
// Create the EscalationPolicy
ResultActions action =
restEscalationPolicyMockMvc.perform(post("/api/escalationPolicys")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(escalationPolicy)));
action.andExpect(status().isCreated());
id = (String)action.andReturn().getResponse().getHeaderValue("policyID");
// Get the created policy
EscalationPolicy e = escalationPolicyRepository.findOne(id);
}
...
}

Spring restful service test case fail HTTP status is 500

I want to implement test case for spring restful web services which return a json
MY controller test class is :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {WebAppContext.class,JpaTestConfiguration.class
})
#WebAppConfiguration
public class DominProfileRestControllerTest {
private MockMvc mockMvc;
#Autowired
private WebApplicationContext webApplicationContext;
private MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
MediaType.APPLICATION_JSON.getSubtype(),
Charset.forName("utf8"));
#Before
public void setUp() {
mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
#Test
public void testGetDomainProfile() throws Exception {
String profileId = domainProfile.getId().toString();
System.out.print("testing restful"+profileId);
mockMvc.perform(get("/service/domainprofile/get/{id}", profileId) )
.andExpect(status().isOk())
.andExpect(content().contentType(contentType))
.andExpect(jsonPath("$.city", is("Chandigrah")));
/* mockMvc.perform(get("/service/domainprofile/get/{id}",profileId).accept(MediaType.TEXT_PLAIN))
.andExpect(status().isOk())
.andExpect(content().contentType("text/plain;charset=ISO-8859-1"))
.andExpect(content().string("hello Prashant"));
*/
}
My Controller class Is :
#RestController
#RequestMapping("/service/domainprofile")
public class DominProfileRestController {
#Autowired
private JpaDomainProfileRepository jpaDomainProfileRepository;
#RequestMapping(value = "/get/{id}", method = RequestMethod.GET)
public DomainProfileResource getDomainProfile(#PathVariable String id) {
JpaDomainProfile domainProfile = jpaDomainProfileRepository.findOne(Long.valueOf(id));
DomainProfileResource domainProfileResource = new DomainProfileResource();
System.out.println("domainProfile.getCity()*************" + domainProfile.getCity());
System.out.println("domainProfile.getAddress()*************" + domainProfile.getAddress());
domainProfileResource.setCity(domainProfile.getCity());
domainProfileResource.setAddress(domainProfile.getAddress());
// return new ResponseEntity<DomainProfileResource>(domainProfileResource, HttpStatus.OK);
return domainProfileResource;
// return domainProfile;
}
}
When I run test case I got An error while we got values in domainprofile.city and domainprofile.address.
Error Is :
java.lang.AssertionError: Status
Expected :200
Actual :500
It Is Working Fine When I return a plain text
can you do this
mockMvc.perform(get("/service/domainprofile/get/{id}", profileId) )
.andDo(print());
this will print the full response with exception , now if you see HttpMessageNotWritableException which was the issue I was facing , you should try to serialize your object using jackson and see if it works (spring internally uses Jackson ). For example , If any of your fields are null the Serialization will fail.

How to implement Rest web service using spring 3?

I have a Library application which is already implemented in spring MVC.
I need to use ReST web services for the same application using spring 3.
I have a Controller class I want is to be as a RestFul webService
#Controller #SessionAttributes("category")
public class CategoryController {
private static final Log log = LogFactory.getLog(CategoryController.class);
#Autowired
private CategoryService categoryService;
#Autowired
private ItemService itemService;
#RequestMapping("/category/categoryList.htm")
public ModelAndView list(HttpServletRequest request,
HttpServletResponse response) throws Exception {
List<Category> list = categoryService.getAllMainCategories();
Map map = new HashMap();
map.put("categoryList", list);
map.put("category", new Category());
return new ModelAndView("categoryList", map);
}
#RequestMapping(method = RequestMethod.POST, value = "/category/save.htm")
public String save(HttpServletRequest request,
HttpServletResponse response, Category command) throws Exception {
log.debug("save method called" + command);
Category category = (Category) command;
System.out.println(category);
categoryService.saveCategory(category);
return "redirect:/category/categoryList.htm";
}
#RequestMapping("/category/edit.htm")
public String edit(#RequestParam String id, ModelMap model)
throws Exception {
log.debug("edit method called :" + id);
log.debug(Long.parseLong(id));
Category cat = categoryService.getCategory(Long.parseLong(id));
model.put("categoryList", categoryService.getAllMainCategories());
model.put("category", cat);
return "categoryList";
}
#RequestMapping("/category/delete.htm")
public String remove(#RequestParam String id, ModelMap model)
throws Exception {
log.debug("remove method called " + id);
categoryService.deleteCategory(Long.parseLong(id));
return "redirect:/category/categoryList.htm";
}
#InitBinder
protected void initBinder(WebDataBinder binder) {
binder.registerCustomEditor(Category.class,
new PropertyEditorSupport() {
#Override
public void setAsText(String text) {
setValue(categoryService.getCategory(Long.valueOf(text)));
}
});
}
}
it is CategoryController class which add delete or update a category
ItemService and CategoryService are data sources
Category is a domain object having properties like id,name,description etc..,
How do I write a REST web service for this?
There's a simple example showing how in Barebones Spring. Check it out.