JUnit Tests for Liferay MVCPortlet using PowerMock - unit-testing

Im trying to make JUnit Test using PowerMock, but I have one problem. Here is my code:
public class MyGreeting extends MVCPortlet {
public static final String GREETING="greeting";
private static final String DEFAULT_GREETING="MY DEFAULT GREETING MESSAGE";
private static final Log _log = LogFactoryUtil.getLog(MyGreeting.class.getName());
#Override
public void render(RenderRequest req,RenderResponse res)
throws IOException, PortletException {
PortletPreferences prefs = req.getPreferences();
req.setAttribute(GREETING, prefs.getValue(GREETING, DEFAULT_GREETING));
super.render(req,res);
}
And I need to make JUnit test. I created another test package, new MyGreetingTest.java file, and come up to this code:
public class MyGreetingTest extends Mockito{
#BeforeClass
public static void setUpBeforeClass() throws Exception {
}
#AfterClass
public static void tearDownAfterClass() throws Exception {
}
private MyGreeting portlet;
#Before
public void setUp() throws Exception {
portlet = new MyGreeting();
}
#After
public void tearDown() throws Exception {
}
#Mock
public RenderRequest request = mock(RenderRequest.class);
#Mock
PortletPreferences preferences = mock(PortletPreferences.class);
#Test
public final void renderTest() throws IOException, PortletException {
when(request.getPreferences()).thenReturn(preferences);
when(preferences.getValue(MyGreeting.GREETING, null)).thenReturn(value);
portlet.render(request, null);
String result = request.getAttribute(MyGreeting.GREETING).toString();
assertEquals(result, value);
}
But I have NullPointerException, because we can't apply getAttribute method to mock-request. Could you please tell me how to solve this problem? How can I test method with getAttribute method using Mockito?

I think you need to mock your method
Stock stock = mock(Stock.class);
when(stock.getPrice()).thenReturn(100.00); // Mock implementation
when(stock.getValue()).thenCallRealMethod(); // Real implementation

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.

Mockmvc Controller throws NullPointerException

maybe someone can tell me why I always get NullPointerException when testing my Controller.
It tells me that the NullPointerException happens here:
mvc.perform(get("/passwordaenderung"))
Here is my code:
public class LagerstandortControllerTest {
#InjectMocks
private PasswordChange passwordChange;
// add #Mock annotated members for all dependencies used by the controller here
private MockMvc mvc;
// add your tests here using mvc.perform()
#Test
public void getHealthStatus() throws Exception {
mvc.perform(get("/passwordaenderung"))
.andExpect(status().isOk())
.andExpect(jsonPath("$.status", is("OK")));
}
#Before
public void createControllerWithMocks() {
MockitoAnnotations.initMocks(this);
MockMvcBuilders.standaloneSetup(new PasswordChange()).build();
}
}
What I want to achieve is to test my controller without loading the whole ApplicationContext.
I had to adapt it in order to avoid a NullPointerException:
Introduced a new class:
public class StandaloneMvcTestViewResolver extends InternalResourceViewResolver {
public StandaloneMvcTestViewResolver() {
super();
}
#Override
protected AbstractUrlBasedView buildView(final String viewName) throws Exception {
final InternalResourceView view = (InternalResourceView) super.buildView(viewName);
// prevent checking for circular view paths
view.setPreventDispatchLoop(false);
return view;
}
}
And in my setup method:
#Before
public void setUp() {
final MainController controller = new MainController();
mvc = MockMvcBuilders.standaloneSetup(controller)
.setViewResolvers(new StandaloneMvcTestViewResolver())
.build();
}
The only problem is now that I get a 404 error.
Do I have to put my index.html in
/src/test/resources
too?

getExchange from mockEndPoint in a unit-test class for Camel Route Not Behaving As Expected

I want to getExchanges from a mockEndPoint in a unit-test class for Camel Route but it doesn't work.
Here is my unit test class:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:camel-unit-test.xml")
public class ImportDatabaseRouteTest extends CamelTestSupport {
#Value("${sql.importDatabase}")
String oldEndPoint;
#Autowired
private ImportDatabaseRoute importDatabaseRoute;
#Autowired
private DriverManagerDataSource dataSource;
#Override
protected RouteBuilder createRouteBuilder() throws Exception {
return importDatabaseRoute;
}
#Before
public void mockEndpoints() throws Exception {
AdviceWithRouteBuilder adviceTest = new AdviceWithRouteBuilder() {
#Override
public void configure() throws Exception {
interceptSendToEndpoint(oldEndPoint)
.skipSendToOriginalEndpoint()
.to("mock:catchCSVList");
}
};
context.getRouteDefinitions().get(0).adviceWith(context, adviceTest);
}
#Override
public boolean isUseAdviceWith() {
return true;
}
#Override
protected JndiRegistry createRegistry() throws Exception {
JndiRegistry jndi = super.createRegistry();
//use jndi.bind to bind your beans
jndi.bind("dataSource", dataSource);
return jndi;
}
#Test
public void testTheImportRoute() throws Exception {
MockEndpoint mockEndPointTest = getMockEndpoint("mock:catchCSVList");
context.start();
List<List<String>> test = (List<List<String>>) mockEndPointTest.getExchanges().get(0).getIn().getBody();
assertEquals("4227",test.get(1).get(0));
assertEquals("370",test.get(1).get(1));
assertEquals("",test.get(1).get(2));
mockEndPointTest.expectedMessageCount(1);
mockEndPointTest.assertIsSatisfied();
context.stop();
}
}
And here are the results:
java.lang.ArrayIndexOutOfBoundsException: 0
at java.util.concurrent.CopyOnWriteArrayList.get(CopyOnWriteArrayList.java:387)
Please help me to fix it. Thank you so much.
You have to assert the mock before you get the exchanges. As those exchanges are the actual exchange that arrived at the mock. So its expectations has to be meet first, which says 1 message should arrive. And if that is success, then you can get that exchange via index 0, and you will not get an IndexOutOfBoundsException
MockEndpoint mockEndPointTest = getMockEndpoint("mock:catchCSVList");
context.start();
// set expectations on mock here
mockEndPointTest.expectedMessageCount(1);
mockEndPointTest.assertIsSatisfied();
// okay now we can get the exchange's from the mock
List<List<String>> test = (List<List<String>>) mockEndPointTest.getExchanges().get(0).getIn().getBody();
assertEquals("4227",test.get(1).get(0));
assertEquals("370",test.get(1).get(1));
assertEquals("",test.get(1).get(2));
context.stop();

handling exception for RestAPI unit test

I have a method
public class ActivityManager {
private ActivityManager activityManager_;
#Autowired
public ActivityManager(ActivityManager activityManage)
{
activityManager_= activityManage;
}
#RequestMapping(value ="activityManager/", method = RequestMethod.GET)
public List<Data> getData() throws RestControllerException {
try {
return activityManage_.fetchData();
} catch (Exception ex) {
throw new RestControllerException();
}
}
}
And I tried to test the throw exception but it does not work. I got confused into the case what's the status() for resultmatcher should be.
#Test(expected = RestControllerException.class)
public void getDataError() throws Exception {
ActivityManager activityManagerMock = Mockito.mock(ActivityManager
.class);
doThrow(RestControllerException.class).when(activityManagerMock).fetchData();
mockMvc_.perform(get("/activityManager")
.contentType(MediaType.APPLICATION_JSON))
.andExpect(status().isInternalServerError());
}
Is there any document that I can read more about handling exception for restapi unit test?
Thanks
#Autowired
private ActivityManagerService activityManager;
This will inject the actual bean into the controller not the mock which you created.
Add this inside your test class.
#Autowired
private ControllerBean controller;
#Before
public void init(){
ReflectionTestUtils.setField(controller, "activityManager", activityManagerMock);
}
This will set the MockObject into activityManager of Controller.
And hence while running test the mock objects fetchData() will be called which inturn throws the exception.

Mockito Mock log4j appender is not invoked while running unit test

I am trying to unit test the log statements generated in my code. I am using slfj, log4j and Mockito. I am using the similar code as below from the blog at
http://bloodredsun.com/2010/12/09/checking-logging-in-unit-tests/
When I run the test it throws exception saying that there are 0 invocations at line:
verify(mockAppender).doAppend(captorLoggingEvent.capture());
Error Message:
Wanted but not invoked: mockAppender.doAppend();
-> at testClass.testLogAdviceAfterReturning(DpsOpsLoggerTest2.java:94) Actually, there were zero interactions with this mock.
I see the logs printed on the console though. Request you to kindly help.
#RunWith(MockitoJUnitRunner.class)
public class ExampleThatLogsTest {
#Mock
private Appender mockAppender;
#Captor
private ArgumentCaptor captorLoggingEvent;
#Before
public void setup() {
LogManager.getRootLogger().addAppender(mockAppender);
}
#After
public void teardown() {
LogManager.getRootLogger().removeAppender(mockAppender);
}
#Test
public void shouldConcatAndLog() {
//given
ExampleThatLogs example = new ExampleThatLogs();
//when
String result = example.concat("foo", "bar");
//then
assertEquals("foobar", result);
verify(mockAppender).doAppend(captorLoggingEvent.capture());
LoggingEvent loggingEvent = captorLoggingEvent.getValue();
//Check log level
assertThat(loggingEvent.getLevel(), is(Level.INFO));
//Check the message being logged
assertThat(loggingEvent.getRenderedMessage(),
is("String a:foo, String b:bar"));
}
}
I tried to emulate your case ,At my end it is working fine
//Log Util
public class LogUtil{
final static Logger logger = Logger.getLogger(LogUtil.class);
public static Log`enter code here`ger getLogger()
{
return logger;
}
//class
public class RunMe {
public String runMe(String parameter) {
LogUtil.getLogger().info("This is info : " + parameter);
return "In runner " + parameter;
}
}
// Unit Test
#RunWith(MockitoJUnitRunner.class)
public class LoggerTest {
#Mock
private Appender mockAppender;
#Captor
private ArgumentCaptor captorLoggingEvent;
#Before
public void setup() {
LogUtil.getLogger().addAppender(mockAppender);
}
#Test
public void shouldConcatAndLog() {
RunMe runner=new RunMe();
String result=runner.runMe("XYZ");
assertEquals("In runner XYZ",result);
verify(mockAppender).doAppend((LoggingEvent) captorLoggingEvent.capture());
LoggingEvent logevent= (LoggingEvent) captorLoggingEvent.getValue();
assertThat(logevent.getLevel(), is(Level.INFO));
}
#After
public void tearDown() {
LogUtil.getLogger().removeAllAppenders();
}
}
I know this is a little bit outdated, but I was struggling with this too. I was logging statements at DEBUG level in the class under test. My configuration in logback.xml for the class under test was set to INFO. Changing my logging statement to INFO allowed the test to pass. In addition, I also read this Github post that is really concise and a clean implementation of testing log output. Hope others will find it useful.