Get service in Rest Controller is not getting called - java

package test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class CommodityControllerTest {
#GetMapping("/api/test")
public void test() {
System.out.println("in controler");
}
}
When I call Get service from POSTMAN, it's not getting called as there is nothing coming in the console.
What I am doing wrong here?
Please let me know if additional information is required.

Try moving the CommodityControllerTest class to the com.miapp.MIApp.controller package.
Your CommodityControllerTest class probably isn't getting picked up during the component scan.
From your screen shot it looks like the class is not in a package. If you just have an #SpringBootApplication annotation on you main class you will need to put your class in a package below where your main class is so that it can find it.

Related

Spring Boot Integration Test with awaitility and #SpyBean not working, because #SpyBean is always null

I want to test my scheduled task, so I followed this tutorial
#SpringJUnitConfig(SchedulerConfig.class)
public class MailJobFinderTaskIT {
#SpyBean
private MailJobFinderTask mailJobFinderTask;
#Test
public void whenWaitThreeSecond_ThenTaskCalledThreeTimes(){
await()
.atMost(Duration.ofSeconds(3))
.untilAsserted(() -> verify(mailJobFinderTask, atLeast(3)).findEmailJobs());
}
}
But actually it does not work, because the the following error
org.mockito.exceptions.misusing.NullInsteadOfMockException:
Argument passed to verify() should be a mock but is null!
Examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
not: verify(mock.someMethod());
Also, if you use #Mock annotation don't miss initMocks()
here is the signature of my Task-Class
#Component
public class MailJobFinderTask extends SuppressedLogPoller {
....
}
#Scheduled(fixedRate = 1000)
public void findEmailJobs() {
.
.
}
I tried already to change the Annotation to #SpringBootTest and also tried to used #MockBean instead of #SpyBean but without any success. Actually I do not understand why my bean mailJobFinderTask is not created
Your code seems to work fine on my system, but I had to do a few changes.
I would recommend these as starting points to your troubleshooting. Also, you haven't mentioned if you can successfully replicate the linked tutorial, which also runs fine on my system. If you haven't, I would recommend trying the tutorial first, confirming it works, and then adding your own code.
If the below does not help you, then it could be that the issue is not in the part of the code you posted. In that case, sharing the full code would help us better troubleshoot the problem. But for now, maybe pay particular attention to the import statements and the main changes listed below.
Changes from your code
I changed the Duration.ofSeconds(3) method to Duration.FIVE_SECONDS. The reason for this is that the former is from java.time package, while await() expects a Duration class from the awaitility package. I just used FIVE_SECONDS for compatibility purposes.
I had to remove the "extends SuppressedLogPoller" part, as I did not have access to this class. I would also recommend removing it and adding this back again to see if it is causing the issue.
Test class code
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.awaitility.Duration;
import static org.awaitility.Awaitility.await;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.verify;
#SpringJUnitConfig(ScheduledConfig.class)
public class MailJobFinderTaskIT {
#SpyBean
private MailJobFinderTask mailJobFinderTask;
#Test
public void whenWaitThreeSecond_ThenTaskCalledThreeTimes(){
await()
.atMost(Duration.FIVE_SECONDS)
.untilAsserted(() -> verify(mailJobFinderTask, atLeast(7)).findEmailJobs());
}
}
Domain class
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
#Component
public class MailJobFinderTask {
#Scheduled(fixedRate = 1200)
public void findEmailJobs() {
}
}
As mentioned in the error message:
Examples of correct verifications:
verify(mock).someMethod();
verify(mock, times(10)).someMethod();
verify(mock, atLeastOnce()).someMethod();
not: verify(mock.someMethod());
You should update the following line:
.untilAsserted(() -> verify(mailJobFinderTask, atLeast(3)).findEmailJobs());
as shown below:
.untilAsserted(() -> verify(mailJobFinderTask, atLeast(3)).findEmailJobs();

Not able to access application.yml properties in springboot component

I have an application.yml file which contains properties as below
NAME:
CLASS:
ID: ABC123456
and here is my spring boot component class
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.util.Arrays;
import java.util.List;
#Component
#Slf4j
public class ProcessMe {
#Value("${NAME.CLASS.ID}")
String StuId;
public boolean IsRightOrWrong(){
System.out.println(StuId);
}
}
In above componenent System.out.println(StuId); is always coming as null. When i am tying to call this function using Junit test class. What's wrong in the above code?
I suppose this solution to define in constructor like
#Component
#Slf4j
public class ProcessMe {
String StuId;
#Autowired
ProcessMe(#Value("${NAME.CLASS.ID}") String StuId) {
this.StuId = StuId;
}
public boolean IsRightOrWrong(){
System.out.println(this.StuId);
}
}
Hope useful
If you can start the application then I believe that your configuration is correct. I mean that StuId have some value.
The problem is how you testing When i am tying to call this function using Junit test class. What's wrong in the above code?
It seems that you're calling from the unit test. Then you need to clone application.yaml to test profile then your test container can read data, otherwise you have to mock your configuration.
btw: Java Object property should using camel case lol

"Class path resource [config/game.properties] cannot be opened because it does not exist" IntelliJ - Spring project not looking in correct directory?

I'm making a Java Spring project in IntelliJ as an exercise and I don't understand a file configuration error I'm having.
Please look at my project directory layout as described in this screenshot:
The three most important files here are the Main & GameConfig classes, and the game.properties file. Or, to use their full package directory names, "console/src/main/java/academy.learnprogramming.console.Main", "core/src/main/java/academy.learnprogramming.config.GameConfig" and core/src.resources.config.game.properties
When I run project, the Main class tries to run the following code:
package academy.learnprogramming.console;
import academy.learnprogramming.MessageGenerator;
import academy.learnprogramming.NumberGenerator;
import academy.learnprogramming.config.GameConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
private static final Logger log = LoggerFactory.getLogger(com.sun.tools.javac.Main.class);
public static void main(String[] args) {
log.info("Guess the number");
//== create the context first ==
ConfigurableApplicationContext context
= new AnnotationConfigApplicationContext(GameConfig.class);
// rest of code, which we never get to because of an error with the above line
When I try to create ConfigurableApplicationContext, I am trying to call the GameConfig class from the Core package. But I get this runtime error instead:
Exception in thread "main"
org.springframework.beans.factory.BeanDefinitionStoreException: Failed
to parse configuration class
[academy.learnprogramming.config.GameConfig]; nested exception is
java.io.FileNotFoundException: class path resource
[config/game.properties] cannot be opened because it does not exist
I do not understand why it thinks GameConfig does not exist, or how to fix it. No solutions I have found seem to have the precise answer for this. I have gotten a configuration comparison from someone whose code is identical to mine, but neither of us understand why their version works and mine does not.
For comparison's sake, the GameConfig class has the following code:
package academy.learnprogramming.config;
import academy.learnprogramming.GuessCount;
import academy.learnprogramming.MaxNumber;
import academy.learnprogramming.MinNumber;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
#Configuration
#ComponentScan(basePackages = "academy.learnprogramming")
#PropertySource("classpath:config/game.properties")
public class GameConfig {
//rest of GameConfig code here...
While game.properties is as simple as this:
game.maxNumber = 100
game.guessCount = 10
game.minNumber = 0
I can't find a question similar to this, nor do other websites point out what's going on. Does anyone have any idea why this error might be happening? Any advice would be invaluable

Annotation RequestMapping() giving the error

I am starting with Spring Boot and trying to make a Rest service.
I am writing a controller where there are RequestMappings to 3 methods.
Two of them are working fine while the thirl annotation is giving this error while writing the code.
Multiple markers at this line
- Syntax error, insert "enum Identifier" to complete EnumHeader
- Syntax error, insert "EnumBody" to complete EnumDeclaration
I tried everything from other answers but cant seem to find out the issue. Here is my code for the Controller-
package io.springboot.topics;
import java.util.Arrays;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
#RestController
public class TopicsController {
#Autowired
private TopicSrvice topicService;
#RequestMapping("/topics")
public List<Topic> getAllTopics() {
return topicService.getAllTopics();
}
#RequestMapping("/topics/{id}")
public Topic getTopic(#PathVariable String id) {
return topicService.getTopic(id);
}
#RequestMapping(method=RequestMethod.POST,value="/topics")
}
The error is coming in the last line ie last Requestmapping().
A bit late but for those that are just finding this issue: You need to type in the actual method under the #RequestMapping. Eclipse gives an issue when you stop at this stage but once you write your method, you are good to go. At least that is what worked for me.
So:
#RequestMapping(method=RequestMethod.POST,value="/topics")
public ... {
//your method
}
You are writing /topics URL for two methods,one for GET and one for POST,Spring does not support this configuration,You can either change url for two different methods or you can write a single method having url /topics with array of HttpMethod like method = { RequestMethod.GET, RequestMethod.POST }

Unit testing annotations?

I'm asking myself how deep should I go in (unit) testing my classes.
As example, I have following simple class .
import javax.annotation.security.PermitAll;
import javax.ejb.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path(value = "ping")
#Singleton
#PermitAll
public class PingRestService {
#GET
#Produces(MediaType.TEXT_PLAIN)
public String pingMethod(){
return "pong";
}
}
I wrote following unit test:
import static org.junit.Assert.*;
import java.lang.reflect.Method;
import javax.annotation.security.PermitAll;
import javax.ejb.Singleton;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import org.junit.Test;
public class PingRestServiceTest {
PingRestService prs = new PingRestService();
#Test
public void testClassAnnotations(){
assertEquals(3, prs.getClass().getAnnotations().length);
assertTrue(prs.getClass().isAnnotationPresent(PermitAll.class));
assertTrue(prs.getClass().isAnnotationPresent(Singleton.class));
assertTrue(prs.getClass().isAnnotationPresent(Path.class));
assertEquals("ping", prs.getClass().getAnnotation(Path.class).value());
}
#Test
public void testPingMethodAnnotations() throws SecurityException, NoSuchMethodException{
Method method = prs.getClass().getDeclaredMethod("pingMethod");
assertEquals(2, method.getAnnotations().length);
assertTrue(method.isAnnotationPresent(GET.class));
assertTrue(method.isAnnotationPresent(Produces.class));
assertEquals(1, method.getAnnotation(Produces.class).value().length);
assertEquals(MediaType.TEXT_PLAIN, method.getAnnotation(Produces.class).value()[0]);
}
#Test
public void testPingMethod() {
assertEquals("pong", prs.pingMethod());
}
}
does it make sense?
Or should I only test the returning string ("pong", testPingMethod), skipping all annotations tests (testClassAnnotations,testPingMethodAnnotations) ?
I think some annotations are part of a business logic (e.g. PermitAll), and therefore should be tested.
Most of the time one tests the functionality of the code and not the way it is implemented. This is called Black Box Testing (see: http://en.wikipedia.org/wiki/Black-box_testing).
When implementing a test you should ask yourself: "What are the possible input values of the unit to test and what are the expected results?"
Now in the test you call your code with the input values and check the result with the expected one to make sure your code behaves the way you want it.
Over time you might optimize the code without wanting to change the functionality. Then you should not need to change your test. But you can re-run it to make sure it still behaves the same way. Even if it is implemented differently. Or you might make change implementation details that have side effects to the functionality you tested. Also in this case you don't need to change the test but you just need to re-run it.
In your simple case you have no input and one static output so you can just call the method and check if "pong" is returned. But real life cases that are tested are rarely that simple.
Edit: You can see the security that #PermitAll configures and the URL path that '#Path' configures as inputs and also test them in an integration test the way 'Boris the Spider' and 'Avi' suggested. But the other annotations are implementation specific.
In my opinion those annotations are aspects of your class and not the essence of it, its real purpose, so shouldn't be unit tested.
Maybe tomorrow you will use Spring MVC instead of JAX-RS, but your class would have the same behavior so the unit test should be the same

Categories