“Invalid use of argument matchers” but I use matchers only - unit-testing

I wish to test the following getRights method:
public GetProductRp getRights(String aaId, String bbId, String ccId) {
GetProductRp rp = (GetProductRp) webServiceTemplate.marshalSendAndReceive(createRq(aaId, bbId, ccId));
return rp;
}
private GetProductRq createRq(String aaId, String bbId, String ccId) {
GetProductRq rq = new GetProductRq();
GetProductRqBody body = new GetProductRqBody();
body.setaaId(aaId);
body.setbbId(bbId);
body.setccId(ccId);
rq.setBody(body);
return rq;
}
This is my test class:
#RunWith(SpringRunner.class)
#SpringBootTest()
public class ClassTest {
#Autowired
private Class rightClass;
#MockBean
private WebServiceTemplate webServiceTemplate;
#Test
public void getRightsTest() throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
GetProductRp response = Helper.createProductRp("xx", "yy");
Method mCreateRq = rightClass.class.getDeclaredMethod("createRq", String.class, String.class, String.class);
mCreateRq.setAccessible(true);
GetProductRq request = (GetProductRq) mCreateRq.invoke(rightClass, "12345678", "12345678", "1111");
Mockito.when(webServiceTemplate.marshalSendAndReceive(request)).thenReturn(response);
Mockito.when(rightClass.getRights(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(response);
Assert.assertNotNull(response);
}
I receive the error provided in the short description above altough I only use Matchers (Mockito.anyString())....
Any idea?

The issue here could be that you are putting #Autowired on private Class rightClass; and you are trying to mock the method of it. If you want to mock the method then you should put #MockBean annotation as :
#MockBean
private Class rightClass;

Related

Junit java.lang.IllegalArgumentException: Could not resolve placeholder 'cors.origin.value' in value "${cors.origin.value}"

It is actually resolved but I will leave here solution if anyone will face the same issue. You have to configure placeholder manually like:
public EventControllerTest() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(eventController)
.addPlaceholderValue("cors.origin.value", "http://localhost:4200")
.build();
}
I am trying to perform simple unit test of some method from controller but I am facing an issue:
java.lang.IllegalArgumentException: Could not resolve placeholder 'cors.origin.value' in value "${cors.origin.value}"
Why is that happen? it is only simple unit test so I do not have to setup whole context for this right?
My code:
request I am calling is API_V1_EVENTS_FIND_BY_GENRE:
public class TestApiUrlStrings {
public static final String API_V1_EVENTS = "api/v1/events";
public static final String API_V1_EVENTS_FIND_BY_GENRE = API_V1_EVENTS + "/Dance?page=0";
}
Unit Test
public class EventControllerTest {
#Mock
EventService eventService;
#InjectMocks
EventController eventController;
MockMvc mockMvc;
public EventControllerTest() {
MockitoAnnotations.initMocks(this);
mockMvc = MockMvcBuilders.standaloneSetup(eventController)
.build();
}
#Test
public void findByGenre() throws Exception {
EventsDTO expected = EventsDTOdatasource.getEventsDTO();
when(eventService.findByGenre(anyString(),anyInt())).thenReturn(expected);
mockMvc.perform(get(TestApiUrlStrings.API_V1_EVENTS_FIND_BY_GENRE)
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.events", hasSize(3)));
}
}
And controller
#Slf4j
#CrossOrigin(value = "${cors.origin.value}")
#RestController
#RequestMapping(EventController.API_V1_EVENTS)
public class EventController {
public static final String API_V1_EVENTS = "api/v1/events";
private final EventService eventService;
public EventController(EventService eventService) {
this.eventService = eventService;
}
#GetMapping("/{musicGenre}")
#ResponseStatus(HttpStatus.OK)
public EventsDTO findByGenre(#PathVariable String musicGenre,
#RequestParam(value = "page", defaultValue = "0") Integer pageNum) {
return eventService.findByGenre(musicGenre, pageNum);
}
#PutMapping
#ResponseStatus(HttpStatus.CREATED)
public EventsDTO saveAll(#RequestBody EventsDTO eventsDTO) {
return this.eventService.saveAll(eventsDTO);
}
}
Why exception is pointing to CORS value where I do not even need it here?
How to resolve this? There is not much about such exception anywhere.

How to write junit test for a rest controller having static method call

I am trying to write a test class for a controller which is having a static method call.
I have used camel producer template to get the result.
I have tried with Mockito but none of them worked for me:
#RestController
#Api(consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
public class TestController{
#Autowired
ProducerTemplate producerTemplate;
#ApiOperation(value = "getdata", notes = "", produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.APPLICATION_JSON_VALUE)
#PostMapping("/getData" )
public ApiResponse<Data> getData(#RequestBody DataRequest request, #RequestHeader HttpHeaders headers, HttpServletResponse response) {
return ApiUtil.makeCall(producerTemplate, "direct:getdata", request,
headers, response);
}
}
public static ApiResponse makeCall(ProducerTemplate producerTemplate, String routerName, Object request,
HttpHeaders headers, HttpServletResponse response) {
HashMap<String, Object> headersMap = null;
ApiResponse apiResponse = producerTemplate.requestBodyAndHeaders(routerName, request, headersMap, ApiResponse.class);
response.setStatus(apiResponse.getHttpCode());
return apiResponse;
}
How can I create unit test case for this controller with static method?
Mockito should be fine here (unless ProducerTemplate is a final class):
#Mock
private ProducerTemplate producerTemplateStub;
#InjectMocks
private TestController testConstrollerSUT;
#Test
public void test() throws Exception(){
// Arrange
when(producerTempalteStub.requestBodyAndHeaders(
eq(routerName), eq(request), any(Map.class), eq(ApiResponse.class)))
.thenReturn(myResponse)
The bottom line is the static method is trivial enough that it does not need to be mocked itself.

How to mock JmsTemplate with Mockito?

I try to test a class where i send a jms message but i can't mock the JmsTemplate
JmsProducer.class :
#Component
public class JmsProducer {
#Autowired
private JmsTemplate jmsTemplate;
#Value("${destination}")
private String destination;
public void send(String message){
jmsTemplate.convertAndSend(destination, message);
}
}
JmsProducerTest.Class :
#RunWith(SpringRunner.class)
public class JmsProducerTest {
private static final String DESTINATION= "example";
private static final String MESSAGE= "message";
#InjectMocks
private JmsProducer jmsProducer;
#MockBean
JmsTemplate jmsTemplate;
#Before
public void init(){
ReflectionTestUtils.setField(jmsProducer, "destinationQueue", DESTINATION);
}
#Test
public void testsend(){
jmsProducer.send(MESSAGE);
verify(jmsTemplate,times(1)).convertAndSend(DESTINATION, MESSAGE);
}
}
And when i run this test case it gives me : java.lang.IllegalArgumentException: object is not an instance of declaring class
Have you any idea for this issue ?
If you are using SpringRunner you should add to the init method MockitoAnnotations.initMocks(this);, because #InjectMocks will be work correct with MockitoJUnitRunner.
PS. ReflectionTestUtils.setField(jmsProducer, "destinationQueue", DESTINATION); - but your fields have another name - destination, not destinationQueue
I would also notice that it could not Mock JmsTemplate and ObjectMapper too with jdk 1.8.05 and when i change the JDK to 1.8.74 it works nice.
I referenced to the discussion

Integration test for authentication filter with Spring Boot

I would like to implement an integration test to test my authentication filter, implemented with Spring Security, with Spring Boot. But... I am lost...
First, here is my "production" implementation:
I have my web configurer adapter creating an authentication manager and declaring my filter:
#EnableWebSecurity
public class SecurityConfigurer extends WebSecurityConfigurerAdapter {
#Autowired
private IdentityService loginService;
#Autowired
private PersonService personService;
#Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(loginService).passwordEncoder(new BCryptPasswordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers(PATH_LOGIN).permitAll();
http.authorizeRequests().antMatchers("/**").fullyAuthenticated();
http.addFilterBefore(new AuthenticationFilter(PATH_LOGIN, authenticationManager(), personService),
UsernamePasswordAuthenticationFilter.class);
}
Then, here is my filter implementation:
public class AuthenticationFilter extends AbstractAuthenticationProcessingFilter {
private ObjectMapper objectMapper = new ObjectMapper();
private PersonService personService;
protected AuthenticationFilter(String loginPath, AuthenticationManager authenticationManager,
PersonService personService) {
super(loginPath);
this.personService = personService;
setAuthenticationManager(authenticationManager);
}
#Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException, IOException, ServletException {
LoginInfo loginInfo = objectMapper.readValue(request.getInputStream(), LoginInfo.class);
UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
loginInfo.getUsername(), loginInfo.getPassword());
Authentication authentication = getAuthenticationManager().authenticate(usernamePasswordAuthenticationToken);
SecurityContextHolder.getContext().setAuthentication(authentication);
return authentication;
}
#Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain,
Authentication authResult) throws IOException, ServletException {
Identity identity = (Identity) authResult.getPrincipal();
Person person = personService.getPersonByMail(identity.getUsername());
UserInfo userInfos = new UserInfo();
userInfos.setUser(person);
userInfos.setRoles(identity.getRoles());
objectMapper.writeValue(response.getWriter(), userInfos);
}
}
Now, I have implemented the two services (PersonService & IdentityService) which should be used as mock to prevent any database access:
#Profile("test")
#Service
public class PersonServiceMock implements PersonService {
private static final Map<String, Person> USER_DB;
static {
Person valerian = new Student();
valerian.setMail("valerian#savetheuniverse.com");
USER_DB = new HashMap<>();
USER_DB.put(valerian.getMail(), valerian);
}
#Override
public Person getPersonByMail(String mail) {
return USER_DB.get(mail);
}
}
-
#Profile("test")
#Service
public class IdentityServiceMock implements IdentityService {
private static final Map<String, Identity> USER_DB;
static {
Identity valerian = new Identity("valerian#savetheuniverse.com");
USER_DB = new HashMap<>();
USER_DB.put(valerian.getUsername(), valerian);
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
USER_DB.forEach((key, value) -> {
value.setEnabled(true);
value.setLocked(false);
value.setPassword(encoder.encode("pa$$w0rd"));
});
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
UserDetails ud = USER_DB.get(username);
return ud;
}
}
In the end, here is my "start of test" I wrote but that does not work because it seems it wants to retrieve the "production" implementation of the service instead of my fake one:
#ActiveProfiles("test")
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class AuthenticationTests {
#Autowired
private Filter filterChainProxy;
#Autowired
private WebApplicationContext context;
private MockMvc mockMvc;
#Before
public void before() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).addFilters(filterChainProxy).build();
}
#Test
public void login() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
LoginInfo loginInfo = new LoginInfo("valerian#savetheworld.com", "pa$$w0rd");
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/login")
.content(objectMapper.writeValueAsString(loginInfo));
Person person = new Student("valerian", "none", "valerian#savetheworld.com");
UserInfo expectedUserInfo = new UserInfo(person, null);
String expectedJSonContent = objectMapper.writeValueAsString(expectedUserInfo);
mockMvc.perform(requestBuilder).andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().json(expectedJSonContent));
}
}
Did I misunderstood something? Can you help me, please?
OK. Never mind. It is just that I misunderstood some notion like mocking, faking & stubbing, even if mocking and stubbing are clearly linked in the unit/integration tests.
I modified my code to remove the different interfaces and the "mock" implementation of the services. This type of implementation is more like a "fake-behaviour" implementation than mocking.
In the end, I have this for my test class:
#RunWith(SpringRunner.class)
#SpringBootTest
#WebAppConfiguration
public class AuthenticationTests {
private static final String KNOWN_USER_MAIL = "valerian#mail.com";
private static final String KNOWN_USER_PASSWORD = "pa$$w0rd";
private static Person KNOWN_STUDENT = new Student("valerian", "none", KNOWN_USER_MAIL);
private static Identity KNWON_IDENTITY = new Identity(KNOWN_USER_MAIL);
static {
BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
KNWON_IDENTITY.setEnabled(true);
KNWON_IDENTITY.setLocked(false);
KNWON_IDENTITY.setPassword(encoder.encode(KNOWN_USER_PASSWORD));
}
#Autowired
// Attribute name very important
private Filter springSecurityFilterChain;
#Autowired
private WebApplicationContext context;
#MockBean // IdentityService automatically mocked when used
private IdentityService identityService;
#MockBean // PersonService automatically mocked when used
private PersonService personService;
private MockMvc mockMvc;
#Before
public void before() {
mockMvc = MockMvcBuilders.webAppContextSetup(context).addFilters(springSecurityFilterChain).build();
// Stub to define the behaviour of the services when they are used
Mockito.when(identityService.loadUserByUsername(KNOWN_USER_MAIL)).thenReturn(KNWON_IDENTITY);
Mockito.when(personService.getPersonByMail(KNOWN_USER_MAIL)).thenReturn(KNOWN_STUDENT);
}
#Test
public void login_success() throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
LoginInfo loginInfo = new LoginInfo(KNOWN_USER_MAIL, KNOWN_USER_PASSWORD);
MockHttpServletRequestBuilder requestBuilder = MockMvcRequestBuilders.post("/login")
.content(objectMapper.writeValueAsString(loginInfo));
UserInfo expectedUserInfo = new UserInfo(KNOWN_STUDENT, KNWON_IDENTITY.getRoles());
String expectedJSonContent = objectMapper.writeValueAsString(expectedUserInfo);
mockMvc.perform(requestBuilder).andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.content().json(expectedJSonContent));
}
}
I am impressed by the magic of the annotation #MockBean and the stubs. :)

How to mock HttpSession in JSF

i have a service method that get session attribute and i want to make unit test for this service method and i was wondering how to mock the HttpSession in jsf.
1- use the FacesContextMocker class:
public abstract class FacesContextMocker extends FacesContext {
private FacesContextMocker() {}
private static final Release RELEASE = new Release();
private static class Release implements Answer<Void> {
#Override
public Void answer(InvocationOnMock invocation) throws Throwable {
setCurrentInstance(null);
return null;
}
}
public static FacesContext mockFacesContext() {
FacesContext context = Mockito.mock(FacesContext.class);
setCurrentInstance(context);
Mockito.doAnswer(RELEASE).when(context).release();
return context;
}
}
2- in the test class #Before method do the following:
FacesContextMocker.mockFacesContext();
ExternalContext externalContext = Mockito.mock(ExternalContext.class);
Mockito.when(FacesContext.getCurrentInstance().getExternalContext())
.thenReturn(externalContext);
HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
Mockito.when(
FacesContext.getCurrentInstance().getExternalContext()
.getRequest()).thenReturn(request);
HttpSession httpSession = Mockito.mock(HttpSession.class);
Mockito.when(GeneralUtils.getHttpSession()).thenReturn(httpSession);
3- the getHttpSession method is as follows:
public static HttpSession getHttpSession() {
return ((HttpServletRequest) FacesContext.getCurrentInstance()
.getExternalContext().getRequest()).getSession();
}
4- in the test method do the following:
Mockito.when(
GeneralUtils.getHttpSession().getAttribute(
"userID")).thenReturn("1");
5- this is assuming that in your service method that you are making the unit test for you have code like:
String currentUserID = (String) GeneralUtils.getHttpSession()
.getAttribute(userID);