I am struggling at wrting unit test, when I test my code block, it says : constructor error
my code below;
#Component
public class CodeConfigBuilder {
#Value("${promoConfig.prefix.length}")
private Integer prefixLength;
public void validateRequestAndSetDefaults(PromoRequest promoRequest) {
prefixAndPostFixControlAccordingToLength(promoRequest);
}
private void prefixAndPostFixControlAccordingToLength(PromoRequest promoRequest) {
if (promoRequest.getPostfix() != null) {
int lengthControl = prefixLength + promoRequest.getPostfix().length();
if (lengthControl >= promoRequest.getLength()) {
throw new BadRequestException(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT);
}
}
}
public void validateRequestAndSetDefaults(PromoRequest promoRequest) {
prefixAndPostFixControlAccordingToLength(PromoRequest promoRequest)
}
my yml configuration below;
#========= Promo Config ========== #
promoConfig:
prefix:
length: 3
my service below;
public void validateRequest(PromoRequest promoRequest) {
codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
}
I have a created PropertySourceResolver class
#Value("${promoGenerationConfig.prefix.length}")
private Integer prefixLength;
and my test class below;
#ExtendWith(SpringExtension.class)
class CodeConfigBuilderTest {
private final PromonRequest promoRequest;
private final PropertySourceResolver propertySourceResolver;
private final PromoService promoService;
private final Request request;
public CodeConfigBuilderTest(PromonRequest promoGenerationRequest, PropertySourceResolver propertySourceResolver, PromoService promoService, Request request) {
this.PromonRequest = PromonRequest ;
this.propertySourceResolver = propertySourceResolver;
this.promoService = promoService;
this.request = request;
}
#Test
void prefixAndPostFixControlAccordingToLength() {
promoService.validateRequest(promoRequest);
int lengthControl = propertySourceResolver.getPrefixLength() + promoRequest.getPostfix().length();
Assertions.assertTrue(true, String.valueOf(lengthControl));
}
I have tried many things but my code does not pass the test it says "org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter"
any help, thank you
I'm not 100% but IMHO you can't use constructor injection in unit tests.
Use this instead:
#SpringBootTest
class CodeConfigBuilderTest {
#Autowired
private PromonRequest promoRequest;
#Autowired
private PropertySourceResolver propertySourceResolver;
#Autowired
private PromoService promoService;
#Autowired
private Request request;
Related
How to pass a ingredientGroup? Or is there some other way?
Controller:
#Controller
#RequestMapping("/ingredients/groups")
#RequiredArgsConstructor
#PermissionUserWrite
public class IngredientGroupController {
private static final String VIEWS_PATH = "/pages/ingredient/group/";
private final IngredientGroupService ingredientGroupService;
#GetMapping("{id}")
public String show(#PathVariable("id") IngredientGroup group, Model model) {
if (group == null) {
throw new ResponseStatusException(HttpStatus.NOT_FOUND, "Ingredient group not found");
}
model.addAttribute("group", group);
return VIEWS_PATH + "show";
}
}
Test:
#SpringBootTest
#AutoConfigureMockMvc
class IngredientGroupControllerTest {
private static final String VIEWS_PATH = "/pages/ingredient/group/";
#Autowired
private MockMvc mockMvc;
#Test
#WithMockAdmin
void show_for_admin() throws Exception {
var ingredientGroup = Mockito.mock(IngredientGroup.class);
mockMvc.perform(MockMvcRequestBuilders.get("/ingredients/groups/{id}", 1))
.andExpect(status().isOk())
.andExpect(view().name(VIEWS_PATH+"show"));
}
}
I don't what the fields are in IngredientGroup. But, I presume that there are fields name and something.
When using an object as #PathVariable, you are expected to pass its properties as query parameters. So, in your case the url you are about to test looks like:
http://localhost:8080/ingredients/groups/1?name=xxxxxx&something=otherthing
#Test
public void show_for_admin() throws Exception {
var ingredientGroup = Mockito.mock(IngredientGroup.class);
mockMvc.perform(MockMvcRequestBuilders.get(String.format("/ingredients/groups/%d", 1),
ingredientGroup.getName(),
ingredientGroup.getSomething()))
.andExpect(status().isOk());
}
I'm New in Mocking.
I've a service I'm trying to call is let say name A, I need to test someMethod.
#Service
public class A {
private Logger logger = LoggerFactory.getLogger(getClass());
private final CoreXReader coreXReader;
#Autowired
B b;
#Autowired
C c;
#Async
public void someMethod(Config config) throws Exception {
pushConfig(config);
}
private void pushConfig(Config config) throws Exception {
String url = config.getBaseurl() + config.getId();
ABCRestClient restClient = new ABCRestClient(url);
String jobJson = restClient.callRestMethod(HttpMethod.GET, "");
}
}
sample of ABCRestClient
public class ABCRestClient {
private Logger logger = LoggerFactory.getLogger(getClass());
private String url;
public ABCRestClient(String url) {
this.url = url;
}
public String callRestMethod(HttpMethod method, String payload) throws Exception {
someresponse="example response";
return someresponse;
}
}
I'm trying to test by creating mockSpy but it still Calling its 'callRestMethod'
#RunWith(SpringRunner.class)
#SpringBootTest // (webEnvironment= SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Test {
#Autowired
private A a;
private Logger logger = LoggerFactory.getLogger(getClass());
#Before
public void prepareMockDataForService() throws Exception {
ABCRestClient apiClient = new ABCRestClient(config.getBaseurl() + config.getId() );
ABCRestClient apiClientSpy=Mockito.spy(apiClient);
doReturn(getCallResponse()).when(apiClientSpy).callRestMethod(HttpMethod.GET, "");
}
#Test
public void TestPushConfig() throws Exception {
a.someMethod(StubDataGenerator.getConfig());
}
private String getCallResponse() {
return "{"msg":"sample response"}";
}
}
i'm not sure what I'm doing wrong here why its calling the actual callRestMethod as i already create a spy .
I tried using this too Mockito.doReturn(getCallResponse()).when(apiClientSpy.callRestMethod(HttpMethod.GET, ""))
Also, is there any difference in these two statement if I use it Mockito.doReturn() or directly doReturn()? In my case both seems behaving same.
Before I tried with this as well when().thenReturn(); but I read somewhere that use when().thenReturn() when you actually want to make call. Please correct if my understanding is wrong.
You can try mock instead of spy:
#RunWith(SpringRunner.class)
#SpringBootTest // (webEnvironment=
SpringBootTest.WebEnvironment.RANDOM_PORT)
public class Test {
#Autowired
private A a;
private Logger logger = LoggerFactory.getLogger(getClass());
#Before
public void prepareMockDataForService() throws Exception {
ABCRestClient apiClientSpy=Mockito.mock(ABCRestClient.class);
doReturn(getCallResponse()).when(apiClientSpy).callRestMethod(HttpMethod.GET, "");
}
#Test
public void TestPushConfig() throws Exception {
a.someMethod(StubDataGenerator.getConfig());
}
private String getCallResponse() {
return "{"msg":"sample response"}";
}
}
I have a class annotated with #Component which is use to initialze application.yml config properties. Service classe is using configuration property. But sometime my Service class instance created before the Configuration class and I get null property value in service class, Its random not specific pattern.
Configuration Initializer class..
#Component
public class ConfigInitializer implements InitializingBean {
private static final Logger log = LoggerFactory.getLogger(ConfigInitializer.class);
#Autowired
ProxyConfig proxyConfig;
/*#PostConstruct
public void postConstruct(){
setProperties();
}
*/
#Override
public void afterPropertiesSet() {
setProperties();
}
private void setSystemProperties(){
log.debug("Setting properties...");
Properties props = new Properties();
props.put("PROXY_URL", proxyConfig.getProxyUrl());
props.put("PROXY_PORT", proxyConfig.getProxyPort());
System.getProperties().putAll(props);
}
}
#Component
#ConfigurationProperties(prefix = "proxy-config")
public static class ProxyConfig {
private String proxyUrl;
private String proxyPort;
public String getProxyUrl() {
return proxyUrl;
}
public void setProxyUrl(String proxyUrl) {
this.proxyUrl = proxyUrl;
}
public String getProxyPort() {
return proxyPort;
}
public void setProxyPort(String proxyPort) {
this.proxyPort = proxyPort;
}
}
Service Class..
#Service("receiverService")
public class ReceiverService {
private static final Logger logger = LoggerFactory.getLogger(ReceiverService.class);
private ExecutorService executorService = Executors.newSingleThreadExecutor();
#Autowired
public ReceiverService() {
initClient();
}
private void initClient() {
Future future = executorService.submit(new Callable(){
public Object call() throws Exception {
String value = System.getProperty("PROXY_URL"); **//Here I am getting null**
logger.info("Values : " + value);
}
});
System.out.println("future.get() = " + future.get());
}
}
Above Service class get null values String value = System.getProperty("PROXY_URL")
When I use #DependsOn annotation on Service class, it works fine.
In my little knowledge, I know Spring does not have specific order of bean creation.
I want to know If I use #Configuration instead of #Component on ConfigInitializer class like below, Will spring initialize ConfigInitializer
class before other beans ?.
#Configuration
public class ConfigInitializer implements InitializingBean {
//code here
}
I have a REST-Backend created with JHipster. There are different exception-classes in the service layer and the web-rest layer. This service-exceptions are translated by an ExceptionTranslator which implements the ProblemHandling interface from org.zalando.problem.spring.web.advice
I have the following ExceptionTranslator:
#ControllerAdvice
public class ExceptionTranslator implements ProblemHandling, SecurityAdviceTrait {
#Override
public ResponseEntity<Problem> process(#Nullable ResponseEntity<Problem> entity, NativeWebRequest request) {
//generated by jHipster
}
#ExceptionHandler(HouseWithoutOwnerServiceException.class)
public ResponseEntity<Problem> handleHouseWithoutOwnerException(HouseWithoutOwnerServiceException ex, NativeWebRequest request) {
return create(new HouseWithoutOwnerException(), request);
}
}
The service-exception class:
public class HouseWithoutOwnerServiceException extends RuntimeException {
public HouseWithoutOwnerServiceException() {
super("House without owner!");
}
}
The rest-error class:
public class HouseWithoutOwnerException extends AbstractThrowableProblem {
private static final long serialVersionUID = 1L;
public HouseWithoutOwnerException() {
super(ErrorConstants.HOUSE_WITHOUT_OWNER_TYPE, "House does not have an owner", Status.CONFLICT);
}
}
In my test the HouseWithoutOwnerServiceException is thrown but not translated into a HouseWithoutOwnerException:
#SpringBootTest(classes = HouseApp.class)
public class HouseControllerIT {
#Autowired
private MappingJackson2HttpMessageConverter jacksonMessageConverter;
#Autowired
private PageableHandlerMethodArgumentResolver pageableArgumentResolver;
#Autowired
private ExceptionTranslator exceptionTranslator;
private MockMvc restHouseMockMvc;
#BeforeEach
public void setup() {
HouseController houseController = new HouseController(houseService);
this.restHouseMockMvc = MockMvcBuilders.standaloneSetup(houseController)
.setCustomArgumentResolvers(pageableArgumentResolver)
.setControllerAdvice(exceptionTranslator)
.setMessageConverters(jacksonMessageConverter)
.build();
}
#Test
#Transactional
public void createHouseWithoutExistingOwner() throws Exception {
HouseDTO houseDTO = createHouseDTOWithoutOwner();
houseDTO.setOwnerId(ownerId + 1); //not existing
restHouseMockMvc.perform(post("/api/v1/houses")
.contentType(TestUtil.APPLICATION_JSON_UTF8)
.content(TestUtil.convertObjectToJsonBytes(houseDTO)))
.andExpect(status().isConflict());
}
}
Therefore I always get 500 Internal Server Error instead of 409 Conflict. I debugged it already and the method in the ExceptionTranslator is not entered.
I have created one scheduler class
public class TestSchedulderNew {
#Scheduled(fixedDelay = 3000)
public void fixedRateJob1() {
System.out.println("Job 1 running");
}
#Scheduled(fixedDelay = 3000)
public void fixedRateJob2() {
System.out.println("Job 2 running");
}
}
In configuration i have put #ConditionalOnProperty annotation to enable this on conditional purpose.
#Bean
#ConditionalOnProperty(value = "jobs.enabled")
public TestSchedulderNew testSchedulderNew() {
return new TestSchedulderNew();
}
Now in controller, i have created "stopScheduler" method to stop those scheduler , in this controller i have autowired
TestSchedulderNew class
#RestController
#RequestMapping("/api")
public class TestCont {
private static final String SCHEDULED_TASKS = "testSchedulderNew";
#Autowired
private ScheduledAnnotationBeanPostProcessor postProcessor; /]
#Autowired
private TestSchedulderNew testSchedulderNew;
#GetMapping(value = "/stopScheduler")
public String stopSchedule(){
postProcessor.postProcessBeforeDestruction(testSchedulderNew,
SCHEDULED_TASKS);
return "OK";
}
}
Now the problem is if conditional property is false then i get below exception
Field testSchedulderNew in com.sbill.app.web.rest.TestCont required a bean of type 'com.sbill.app.schedulerJob.TestSchedulderNew
In case of true everything works fine,
Do we have any option to solve this ?
You can use #Autowired(required=false) and null check in stopScheduler method.
#Autowired(required=false)
private TestSchedulderNew testSchedulderNew;
#GetMapping(value = "/stopScheduler")
public String stopSchedule() {
if (testSchedulderNew != null) {
postProcessor.postProcessBeforeDestruction(testSchedulderNew,
SCHEDULED_TASKS);
return "OK";
}
return "NOT_OK";
}