Showing posts with label unit test. Show all posts
Showing posts with label unit test. Show all posts

Sunday, December 6, 2015

Hijacking the logger, so rude!

Last Friday could be my happiest day in 2015 because I've figured out how could I override log4j logger in unit test. Take the use case below as an example, I'll have the logger being declared as private static member:
import org.apache.log4j.Logger;

public class Helper {
   private static Logger jdbcLogger = Logger.getLogger("jdbcLogger");

   ...
   ...
}
This was a nightmare because JDBC logger is very high depends on the database's availability, especially when I've been told to freeze any update into the database. End up I create a local database just for this purpose, by doing so, I'm required to reconfigure the JDBC connection in my source code. This still isn't a clean solution as I don't want Jenkins to reconfigure the database configuration in the raw code. Then I start to think about the hijacking way, this is what I did to hijack the logger:
private void hijackJdbcLogger() {
   Logger l = Whitebox.getInternalState(Helper.class, "jdbcLogger");
   l.removeAllAppenders();
   l.addAppender(appender);

   Whitebox.setInternalState(Helper.class, "jdbcLogger", l);
}
But later I found out this solution has a flaw where jdbcLogger must first initialize by Helper class before I can change its value. At least I have something surprise me where I mock the whole logger:
@BeforeClass
public static void setUpBeforeClass() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
   Logger mockLogger = Logger.getLogger("unitTestLogger");
   mockLogger.setLevel(Level.DEBUG);
   mockLogger.setAdditivity(false);
   mockLogger.addAppender(EasyMock.createMock(ConsoleAppender.class));

   Field logger = ReportHelper.class.getDeclaredField("jdbcLogger");
   logger.setAccessible(true);
   logger.set(null, mockLogger);
}
Now I feel the perfection with this solution design. Again, in rule of design, hijacking is very rude, don't do this. When something has declared as private, meaning it is not suppose to be exposed to the outside world. Code review is indeed a higher priority in such case.

Tuesday, December 1, 2015

No last call on EasyMock

I have a static function which is as simple as following:
public class Utility {
   public static String funcA() {
      return "ABC";
   }
}
I was shock seeing the following error when I am unit testing the Utility class:
java.lang.IllegalStateException: no last call on a mock available
 at org.easymock.EasyMock.getControlForLastCall(EasyMock.java:560)
 at org.easymock.EasyMock.expect(EasyMock.java:538)
 at org.huahsin.unittest.theprocess(SUT.java:72)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606)
 at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
 at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:88)
 at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:96)
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
 at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
 at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
 at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
 at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:122)
 at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:106)
 at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
 at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:59)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192
The error message is quite confusing to me because this is to indicate that EasyMock was unable call the function as the function is being declared as static. Since EasyMock unable to handle static method, then PowerMock would be my best fit on this matter.

To allow EasyMock to see static method, I have to make an announcement to EasyMock that I'm sending in a class with static method and I'm going to unit test it now.
@RunWith(PowerMockRunner.class)
@PrepareForTest(Utility.class)
public class SUT {
   @BeforeClass
   public static void setUpBeforeClass() {
      PowerMock.mockStatic(Utility.class);
   }

   @Test
   public void theprocess() throws InvalidDataFileException {
      EasyMock.expect(Utility.funcA()).andReturn("genius");

      PowerMock.replayAll();

      /***** start test code when mock code are done *****/
   }
}
Then only EasyMock will know what to do. Do remember to call PowerMock.replayAll() to get the mock objects ready, otherwise EasyMock wouldn't recognize them.

Tuesday, November 24, 2015

JSF session in JMeter

Just a quick note, when running performance tests on JSF using JMeter, in order to successfully execute a single thread (single user), not even mention execute multiple thread (more than one user) at a time, a new JSF View State value need to be captured every time a thread start executes. Otherwise the test will fail, even though it was recorded through Recording Controller. To capture the new JSF view state value, I create a new Regular Expression Extractor post processor under the GET request and put in following details:

Parameter Name Value
Reference Name jsfViewState
Regular Expression id=\"javax.faces.ViewState\" value=\"(.+?)\"
Template $1$
Match No. (0 for Random)   1

And then in the POST request which fail in the test, replace the javax.faces.ViewState‘s parameter value with ${jsfViewState}. After this, I also need an HTTP Cookie Manager to be placed in thread group to make it work.

Sunday, November 22, 2015

My new reinforcement on C++ unit test

A few weeks ago, while I was working out on CppUnit in unit testing and I found out that it wouldn’t work as I doesn’t have MFC framework install in my Windows. Now I had discovered Boost.Test for this critical mission. The first contact on the new discovery, I have following code ready to charge:
#define BOOST_TEST_MODULE Hello
#include <boost/test/unit_test.hpp>

int add(int i, int j)
{
    return i+j;
}

BOOST_AUTO_TEST_CASE(Case1)
{
    BOOST_CHECK(add(2,2) == 4);
}
Interestingly, the test doesn’t get executed, but the main entry point of the program, int main(int argc, char* argv[]) was called. I spent the whole day reading through the documentation still has not got any clue on it. Until I remove the main entry point, and something were shown on the screen:
Running 1 test case...

*** No errors detected
Press <return> to close this window...
This is pretty exciting as I got a first unit test up and running. Thinking out from the plan, I need a separate project just for the unit test.

Saturday, November 14, 2015

initializationError occurred in unit testing

What a bad day.

It has been so long I never run my unit test since many versions has been update to the source code. According to experts, unit test must run once in a while to ensure the codes are still working as expected. But today when I execute the unit test, it shows me an initializationError. What the heck!! What is wrong with my code? This error was occurred even before any unit test codes were run.

As I check in the forum, this may cause by the classpath containing two different versions of Hamcrest. But looking at my classpath, I don’t see two Hamcrest whereas I see two Junit libraries in the classpath, one provided by Eclipse and another one provided by Powermock. Would this be the root cause of this error? Hmmm… try to remove the one provided by Eclipse, it works! What the heck!

Thus, the conclusion would be either use the Junit provided by Eclipse or import my own Junit.

Saturday, November 7, 2015

CppUnit require MFC library on Windows environment?!!

Anyone done any unit testing on C++? Am I speaking on my own?

Well, I was influenced by the unit testing I did in Java. After many years of working on C/C++ program, now only got to realize I was actually missing unit testing in the development. I was so curious why none of them mention this before? Or maybe they felt that unit testing is a waste? Or they don’t even care? But in Java world, they are so concern about unit testing. Anyhow, I just download a copy of the unit testing framework – CppUnit, and putting it into my very personal, private, secret project.

Just a site note when getting the source of CppUnit, never download from the website, it was a trap. This is because the files are suffixed with “,v” in the file extension. The real source ca be download through SVN. Once done, build it. There is no free lunch in the open source world.

When I was about to build, Oh No!! How to build on Windows machine? configure and make are only workable command in Linux…

Well, the instruction was in the file with file name start with INSTALL, there are many of them. In my case, I’m building it in a Windows environment, thus I’ll look for the INSTALL-WIN32.txt. Follow the instructions mention in that file to build CppUnit. Unfortunately, the building of CppUnit has failed due to the missing of afxwin.h. Since I’m using visual studio express edition, this edition doesn’t have MFC installed, thus it wouldn’t have that header file.

Crap! What a bad day.

Thursday, July 23, 2015

What the hell? Wrong instance of javax/management/MBeanServer?

Arghhhhh! This error happened again! I’m feeling weird on this error as I never invoke any MBeanServer thing in my code. And this error sound familiar to me, I think I have seen the similar error happened before, but I couldn’t recall my memory. I wasn't sure whether this is a common defect only happened on Powermock 1.6 but it is quite annoying me.
Caused by: java.lang.LinkageError: loader constraint violation: loader (instance of org/powermock/core/classloader/MockClassLoader) previously initiated loading for a different type with name "javax/management/MBeanServer"
 at java.lang.ClassLoader.defineClass1(Native Method)
 at java.lang.ClassLoader.defineClass(ClassLoader.java:800)
 at java.lang.ClassLoader.defineClass(ClassLoader.java:643)
 at org.powermock.core.classloader.MockClassLoader.loadUnmockedClass(MockClassLoader.java:237)
 at org.powermock.core.classloader.MockClassLoader.loadModifiedClass(MockClassLoader.java:182)
 at org.powermock.core.classloader.DeferSupportingClassLoader.loadClass(DeferSupportingClassLoader.java:68)
 at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
 at org.apache.logging.log4j.core.jmx.Server.unregisterAllMatching(Server.java:307)
 at org.apache.logging.log4j.core.jmx.Server.unregisterLoggerContext(Server.java:229)
 at org.apache.logging.log4j.core.jmx.Server.reregisterMBeansAfterReconfigure(Server.java:140)
 at org.apache.logging.log4j.core.jmx.Server.reregisterMBeansAfterReconfigure(Server.java:119)
 at org.apache.logging.log4j.core.LoggerContext.setConfiguration(LoggerContext.java:356)
 at org.apache.logging.log4j.core.LoggerContext.reconfigure(LoggerContext.java:386)
 at org.apache.logging.log4j.core.LoggerContext.start(LoggerContext.java:149)
 at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:84)
 at org.apache.logging.log4j.core.impl.Log4jContextFactory.getContext(Log4jContextFactory.java:35)
 at org.apache.logging.log4j.LogManager.getLogger(LogManager.java:444)
 at com.awpl.worker.AbstractWorker.<init>(AbstractWorker.java:60)
 at com.awpl.worker.WorkerWithTriggerFile.<init>(WorkerWithTriggerFile.java:22)
 at com.awpl.worker.WorkerWithTriggerFileTest.throwFileNotFoundException(WorkerWithTriggerFileTest.java:23)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:606) at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
 ... 23 more 
So what I did is just ignore this particular error and my unit test is proceed as usual:
 @PowerMockIgnore({"javax.management.*"})
 public class TheClassTest {
    …
 }

Sunday, January 11, 2015

How could I unit test inner class?

Given the source code below, how could I effectively unit test the Message class, the inner class of MainMsg? The challenge for this use case is Message class doesn't have any public interface that could access from outside world, the only entry is from MainMsg's addMessage(). How could I return a fake data when getMsgList() is called? Or I shouldn't mock Message class actually, just instantiate a new value is more than enough.
public class MySystem {
 public static void getMessage(MainMsg mm) {
  if( mm.getMsgList().size() > 0 ) {
   … 
   … 
  }
 }
}

public class MainMsg {
 private List<Message> msgList = new ArrayList<Message>();
 public class Message {
  private String str;
  Message(String str) {
   this.str = str;
  }
 }
 public void addMessage(String content) {
  msgList.add(new Message(content));
 }
 public List<Message> getMsgList() {
  return msgList;
 }
}
According to the advice from expert, I shouldn’t mock the inner class, whereas I should create a real value of it. But how? After a long R&D, I found EasyMock could handle this very well. In my unit test class, this is how I did it:
@RunWith(PowerMockRunner.class)
@PrepareForTest({MySystem.class})
public class MySystemTest {
 private MainMsg mm;
 @Test
 public void testSendMessage () throws IOException {
  mm = PowerMock.createPartialMock(MainMsg.class, "getMsgList");
  EasyMock.expect(mm.getMsgList()).andStubAnswer(new IAnswer<List<Message>>() {
   @Override
   public List<Message> answer() throws Throwable {
    Whitebox.setInternalState(mm, new ArrayList<Message>());
    mm.addMessage("message_A");
    List<Message> fakeMsgList = Whitebox.getInternalState(mm, "msgList");
    return fakeMsgList;
   }
  });

  MySystem.getMessage(mm);
 }
}

Monday, December 1, 2014

NoSuchMethodError on org.hamcrest.Matcher.describeMismatch

I found an interesting error when I have the following code being used in my unit test:

Assert.assertThat(((LoggingEvent) loggingEvent.getValue()).getLevel(), CoreMatchers.is(Level.DEBUG));

Following stacktrace could be seen:
java.lang.NoSuchMethodError: org.hamcrest.Matcher.describeMismatch(Ljava/lang/Object;Lorg/hamcrest/Description;)V 
 at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:18) 
 at org.junit.Assert.assertThat(Assert.java:865) 
 at org.junit.Assert.assertThat(Assert.java:832) 
 at org.huahsin68.EmployeeImplTest.test(EmployeeImplTest.java:62) 
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 
 at java.lang.reflect.Method.invoke(Method.java:622) 
 at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68) 
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310) 
 at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:88) 
 at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:96) 
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294) 
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127) 
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82) 
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282) 
 at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86) 
 at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49) 
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207) 
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146) 
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120) 
 at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33) 
 at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45) 
 at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118) 
 at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:101) 
 at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53) 
 at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53) 
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

An expert told me that never use the hamcrest came from JUnit 4, I'm require to download a separate hamcrest library (it is version 1.3 as of this writing), and it must come before JUnit 4 in the build path. What he told is true.

How could I unit test on the message came from log4j?

I was ask to unit test every single function that I wrote, and I was so unlucky that every function I wrote do invoke log4j. I was thinking whether I should cover those in my unit test as well? There is not much resources found on Internet, mat be due to the reason this really waste of effort or they are more concern on the logic design than this. But I'm so curious on how the code is if I'm insist to go with it. For the purpose of this, I have create an POC as shown below. Let's assume I'm going to unit test on funcA():
public class EmployeeImpl { 

 private static Logger log; 

 public static void initLog() { 
   
  log = Logger.getLogger(EmployeeImpl.class); 
  log.setLevel(Level.INFO); 
  log.setAdditivity(false); 
   
  ConsoleAppender ca = new ConsoleAppender(); 
  ca.setWriter(new OutputStreamWriter(System.out)); 
  ca.setLayout(new PatternLayout("%-5p [%t]: %m%n")); 
  log.addAppender(ca); 
 } 
  
 public static void funA() { 
  log.info("Entering into funcA"); 
 } 
}

Next I have my unit test as shown below targeting on funcA():
@RunWith(PowerMockRunner.class)
public class EmployeeImplTest { 
  
 @Mock 
 private Appender appenderMock; 
  
 @Captor 
 private ArgumentCaptor<loggingevent> loggingEvent; 

 @Test 
 public void test() throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException { 
   
  Logger.getRootLogger().addAppender(appenderMock); 
   
  Field log = EmployeeImpl.class.getDeclaredField("log"); 
  log.setAccessible(true); 
  log.set(null, LogManager.getLogger(EmployeeImpl.class)); 
   
  EmployeeImpl.funA(); 
   
  Mockito.verify(appenderMock, Mockito.times(1)).doAppend((LoggingEvent) loggingEvent.capture()); 
  Assert.assertThat(((LoggingEvent) loggingEvent.getValue()).getLevel(), CoreMatchers.is(Level.INFO)); 
  Assert.assertThat(((LoggingEvent) loggingEvent.getAllValues().get(0)).getRenderedMessage(), CoreMatchers.equalTo("Entering into funcA")); 
 } 
}
Tada!! The test case above test 2 things; 1) Ensure the log level is INFO, 2) Ensure the message Entering into funcA. were shown. Either one is incorrect will failed the test case. In this case, the result will be pass.

Sunday, May 25, 2014

Work around to authenticate during unit testing on Spring MVC

Following method is the "usual practice" used in unit testing the authentication on Spring MVC.
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(value = {"classpath:/WEB-INF/Project-servlet.xml", "classpath:/WEB-INF/security.xml", "classpath:/WEB-INF/datasource.xml", "classpath:/WEB-INF/user.xml"})

public class HelloControllerTest extends AbstractJUnit4SpringContextTests {

 private MockMvc mockMvc;
 
 @Autowired
 private WebApplicationContext wac;
 
 @Autowired
 @Qualifier("authServiceProvider4")
 private UserDetailsService userDetailsService;

 @Autowired
 private FilterChainProxy proxy;
 
 @Before
 public void setUp() {
  mockMvc = MockMvcBuilders.webAppContextSetup(wac).addFilter(proxy).build();
 }

 @Test
 public void testUserWithAdminRoleLandOnWelcomeUrl() throws Exception {
  
  UserDetails ud = userDetailsService.loadUserByUsername("user1");
  Authentication auth = new UsernamePasswordAuthenticationToken(ud.getUsername(), ud.getPassword(), ud.getAuthorities());
  SecurityContextHolder.getContext().setAuthentication(auth);

  ...

  mockMvc.perform(get("/welcome"))
   .andExpect(status().isOk());

 }
}
Code sample above showing a test method testing on valid user, user1, landing on welcome site which require admin role in order to render the page. Somehow the test were failed, and following failure trace were seen:
java.lang.AssertionError: Status expected:<200> but was:<302>
 at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
 at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
 at org.springframework.test.web.servlet.result.StatusResultMatchers$5.match(StatusResultMatchers.java:546)
 at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:141)
 at org.huahsin.sit.HelloControllerTest.testUserWithAdminRoleLandOnWelcomeUrl(HelloControllerTest.java:101)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
 at java.lang.reflect.Method.invoke(Method.java:622)
 at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:47)
 at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
 at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:44)
 at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
 at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
 at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
 at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
 at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
 at org.junit.runners.ParentRunner$3.run(ParentRunner.java:238)
 at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:63)
 at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:236)
 at org.junit.runners.ParentRunner.access$000(ParentRunner.java:53)
 at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:229)
 at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
 at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
 at org.junit.runners.ParentRunner.run(ParentRunner.java:309)
 at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
 at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)


From what I understand from this answer, the session of user1 were gone missing, I need to hold the session of user1 when MockMvc doing its work. To do this, a mocking session class is require:
    public static class MockSecurityContext implements SecurityContext {

        private static final long serialVersionUID = -1386535243513362694L;

        private Authentication authentication;

        public MockSecurityContext(Authentication authentication) {
            this.authentication = authentication;
        }

        @Override
        public Authentication getAuthentication() {
            return this.authentication;
        }

        @Override
        public void setAuthentication(Authentication authentication) {
            this.authentication = authentication;
        }
    }
After that create a mock session and pass it to MockMvc to perform its test work.
 @Test
 public void testUserWithAdminRoleLandOnWelcomeUrl() throws Exception {
  
  UserDetails ud = userDetailsService.loadUserByUsername("user1");
  Authentication auth = new UsernamePasswordAuthenticationToken(ud.getUsername(), ud.getPassword(), ud.getAuthorities());
  SecurityContextHolder.getContext().setAuthentication(auth);

  MockHttpSession session = new MockHttpSession();
  session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, new MockSecurityContext(auth));

  mockMvc.perform(get("/welcome").session(session))
   .andExpect(status().isOk());

 }

Saturday, February 22, 2014

@Rule allows me to verify the message

Nice sharing from Stackoverflow peer suggesting a new solution on testing exception. This adds more flexibility to my test. Assuming I'm testing on a class that throw NullPointerException:
public class ClassCauseException {

 public void funcA() throws NullPointerException {
  throw new NullPointerException("Some NULL message");
 }
}
Usually I'll do this:
 @Test(expected=NullPointerException.class)
 public void testFuncB() {
  ClassCauseException c = Mockito.spy(new ClassCauseException());
  c.funcA();
 }
That will only tells me funcA will throw an NullPointerException. But I couldn't verify whether whether the right message is display. Anyhow there is a more elegant way for this issue. With @Rule, I'm allow to verify whether the display message when an Exception is being thrown. For example, when the following test is execute, I'm expecting an NullPointerException will be throw, and a message The NULL value should be display. Eventually the test will failed due to the actual message Some NULL message is display.
public class RuleExceptionTest {

 @Rule
 public ExpectedException exp = ExpectedException.none();
 
 @Test
 public void testFuncA() {
  exp.expect(NullPointerException.class);
  exp.expectMessage("The NULL value");
  ClassCauseException c = new ClassCauseException();
  c.funcA();
 }

}
This could be useful if I care the type of Exception being thrown and what message is being display.

Tuesday, January 14, 2014

Selenium not navigate to given URL

What a silly day for me! I was setting up a Selenium project using Maven in Eclipse IDE, somehow the browser was launched but not navigating to the given URL. It just showing blank screen after launched.

Remember in some years back, I have encountering this issue before but this problem is due to the network was behind a proxy server. Since I'm doing it at home, I'm sure I don't have any proxy server setup. I give up to do it on Maven, make it a traditional project, import the Selenium JAR manually. It works! (What a joke!)

I spend my whole day looking at the source code, searching for the root cause then only I find out it is actually cause by the Maven configuration. Code snippet below shows the original Maven configuration:
  <dependencies>
    <dependency>
      <groupid>junit</groupid>
      <artifactid>junit</artifactid>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
     <groupid>org.seleniumhq.selenium</groupid>
     <artifactid>selenium-remote-driver</artifactid>
     <version>2.33.0</version>
    </dependency>
    <dependency>
     <groupid>org.seleniumhq.selenium</groupid>
     <artifactid>selenium-firefox-driver</artifactid>
     <version>2.33.0</version>
    </dependency>
  </dependencies>
See that the Selenium version number was set to 2.33, have a check on the Selenium site (as of this writing), the latest version was 2.39. To conclude this, using the wrong version may cause the Selenium not navigate to the given URL.

Friday, January 10, 2014

A good design in classes could make Mockito happier

I am having difficulty on executing a unit test that will throw ClassNotFoundException when an error has occurred. But later I found out that this difficulty isn’t come from the limitation of the test framework (Mockito or PowerMock) but it is due to the design problem in my class. I think I should aware of this problem during the development stage but why I only see it during unit test stage? Not only this design is impractical but it also makes the unit test execution even harder. Consider the following scenario, I have initConnection() declared in base class, and this method is invoke from the subclass:
public abstract class ReportService {

 ...
 ...

 protected void initConnection() {
  try {
   ...
   ...

  } 
  catch(HibernateException e) {
   e.printStackTrace();
  } 
  catch (ClassNotFoundException e) {
   e.printStackTrace();
  }
 }
}

public abstract class HibernateReportService<T> extends ReportService {

 ...
 ...

 public void execute() {
  
  try {
   initConnection();

   ...
   ...
  }
  finally {
  }

 ...
}
Assuming I want to verify ClassNotFoundException is thrown when an error has occurred. If I initiate the test execution using following code snippet, this will cause the test failed because the exception has been caught in base class.
 @Test(expected=ClassNotFoundException.class)
 public void testInitConnectionClassNotFoundException() throws Exception {
  ...
  ...
Suddenly, my mind raise up a very interesting question to me, am I doing the thing right? Am I coding the right thing? According to the best practices, I should not catch the exception in base class whereas I should escalate to the subclasses to handle the exception. By following this design, changes were made on the base code, initConnection() will no longer catching any exception:
 protected void initConnection() throws ClassNotFoundException {
  ...
 }
When I execute the unit test code above, the test was finally passed. Something has been clear in my mind now, during Whitebox testing, the test is not to check whether the exception has been handles properly but to verify what will be the behavior if an exception has been thrown. Put in other words, exception must throw during Whitebox testing. When handover to test team, then only tester will need to verify those exceptions being handles properly through a series of black box testing, not during Whitebox testing.

Thursday, January 9, 2014

Impractical use of doCallRealMethod() when object being spy

Oh no! Another mistake in this morning. Although the code sound true but the code doesn't sound logic. Take a look at the code snippet from previous note as an example:
public class FileClass {
 public void funcB() {
  
  try {
   throw new ClassNotFoundException();
  }
  catch( ClassNotFoundException e ) {
   ...
  }
 }
}
Due to the misunderstanding between mock and spy, the following test code isn’t really practical because ClassFile is already in spy mode, the use of doCallRealMethod() is just a waste, thus invoking the real instance is more than enough. doCallRealMethod() is usable if and only if FileClass is a mock.
 @Test(expected=ClassNotFoundException.class)
 public void testFuncB() throws ClassNotFoundException {
  FileClass fc = Mockito.spy(new FileClass());
  Mockito.doCallRealMethod().when(fc).funcB();
  fc.funcB();
 }

Wednesday, January 8, 2014

Invalid use of doThrow() with spy object

Things happened in this morning really embracing me. I’ve made a huge mistake in my programming life because I was confuse on the usage between Mockito.spy() and Mockito.mock().
public class FileClass {
 public void funcB() {
  
  try {
   throw new ClassNotFoundException();
  }
  catch( ClassNotFoundException e ) {
   ...
  }
 }
}
Suppose I have the above class ready for unit test, take note that I have try...catch surrounding the throw statement. My objective is to test whether ClassNotFoundException will be thrown when funcB() is invoke. If I execute the unit test code below, the test will fail with java.lang.AssertionError: Expected exception: java.lang.ClassNotFoundException.
public class TestMainApp {

 @Test(expected=ClassNotFoundException.class)
 public void testFuncB() throws ClassNotFoundException {
  FileClass fc = Mockito.spy(new FileClass());
  fc.funcB();
 }
}
The result of this test was actually fail. The reason being why this test was failed is because the throw statement in funcB() has already been catch. Since the exception has already catch, there were no more exception being escalate from funcB() when the control return to testFuncB(). In order to make this work, I think of a workaround solution. I modify the test code to mimic the ClassNotFoundException is being thrown:
 @Test(expected=ClassNotFoundException.class)
 public void testFuncB() throws ClassNotFoundException {
  FileClass fc = Mockito.spy(new FileClass());
  
  Mockito.doThrow(new ClassNotFoundException())
  .when(fc).funcB();
  
  fc.funcB();
 }
Smart right? NO! This code has actually cause the unit test run even worst. Now I can see MockitoException shown in the stack trace:
java.lang.Exception: Unexpected exception, expected but was
 ... 
 ... 
 ... 
Caused by: org.mockito.exceptions.base.MockitoException: 
Checked exception is invalid for this method!
Invalid: java.lang.ClassNotFoundException
 ... 
 ... 
This is a big mistake. Whenever the class is under test, never mock on the class, just invoke the real instance. Put in the practical way, the use of doThrow() is invalid here because I’m not doing any mock on FileClass. Never think of remove the surrounding try...catch block because this has violated my original design even though it’s working fine.

Saturday, January 4, 2014

Invoke protected method with PowerMockito

My objective is to invoke the real execution of a method during the unit test. The hardest part on running this unit test is I'm targeting on a protected method. Mockito couldn’t do well with this, but PowerMockito do provide a very good solution on private/protected method. Following scenario shows how the existing classes were designed, and the target method that I’m going to unit test is initConnection().
public abstract class ReportService {

 ...

 protected void initConnection() {
  try {
   Class.forName("com.informix.jdbc.IfxDriver");
   
   session = HibernateUtil.currentSession();
   session.beginTransaction();
  } catch(Exception e) {
   e.printStackTrace();
  }
 }

 ...
}

public abstract class HibernateReportService<T> extends ReportService {

 ...

 public void execute() {
  
  try {
   initConnection();

   ...
   ...

}
To achieve my objective, there are 2 possible ways for the setup in my stub code. It is either Method 1:
 public void initConnectionCallRealMethod() throws Exception {
  PowerMockito
   .when(this.daoReportService, PowerMockito.method(ReportService.class, "initConnection"))
   .withNoArguments()
   .thenCallRealMethod();
 }
Or Method 2:
 public void initConnectionCallRealMethod() throws Exception {
  PowerMockito.doCallRealMethod()
   .when(this.daoReportService, PowerMockito.method(ReportService.class, "initConnection"))
   .withNoArguments();
 }
}
this.daoReportService is an instance of object that extends from HibernateReportService which is being spy. And also notice the use of PowerMockito.method(), this is due to the reason initConnection() is not visible to the outside world, thus the regular use of when() will not going to work.

Wednesday, December 25, 2013

Implementing a test stub pattern

First thing first, I don’t create this pattern. I got this idea when I was reading the unit testing strategy from this blog. I like this test pattern because the codes were so clean and very object oriented style. (Before this my unit test code were very messy just like spaghetti). This way, I can easily isolate my mock code into a standalone stub class without messing up with real method.

Before I start using this pattern, let’s see how this pattern could fit into my project. I pick reporting template module for this experiment, which is my favourite module because this module is like a Sergeant who able to tackle different type of reporting problem. The UML diagram below shows the real design on the report template module.

In order to utilize its reporting service, one must inherit HibernateReportService because this class was declare as abstract, and it is the only interface that has contact to the outside world, and all the initialization work are done through the constructor. The query method is the only entry point that could allow customizes query selection in order to complete the reporting job. Code snippet below shows its use:
public class MyReportService extends HibernateReportService<Object> {

    public MyReportService(...) {
        ...
    }

    protected void query() {
        ...
    }

}
There would be a difference when come to initializing the report template unit testing work. As according to the design, I don’t inherit HibernateReportServiceStubber from HibernateReportService, whereas I make a generic template of HibernateReportService type. This idea was great as it allow me to isolate the mock code or fake implementation without messing up with the real implementation in HibernateReportService. Code snippet below showing the primary piece that makes up this stub class:
public class HibernateReportServiceStubber<T extends HibernateReportService<Object>> {

 private T daoReportService;

 public HibernateReportServiceStubber(T daoService) throws Exception {
  
  // capture the DAO that going to be test
  this.daoReportService = PowerMockito.spy(daoService);
 }
 
 public T getReportService() {
  return this.daoReportService;
 }

 // more mock method down the road
} 
Here come to the unit test guy. TheReportingServiceTest is the guy that takes up responsibility to execute the test. Again this guy doesn’t inherit from HibernateReportServiceStubber but he instantiate it and execute the fake implementation provided from the stub class. Below is the sample of his hard work:
public class TheReportingServiceTest {

 private HibernateReportServiceStubber<MyReportService> reportServiceStubber;
 
 @Before
 public void setUp() throws Exception {
  reportServiceStubber = getHibernateReportService();
 }

 private HibernateReportServiceStubber<MyReportService> getHibernateReportService() throws Exception {
  return new HibernateReportServiceStubber<MyReportService>(new MyReportService (...));
 }

 @Test
 public void test(){
  reportServiceStubber.mockCodeA();
  reportServiceStubber.mockCodeB();

  ...
 }

} 
At the end of this experiment, I feel that I'm actually running a behavioural test more than running unit testing on each single detail function/method.

Return a mock value when an object is being spy

My objective is to develop a test stub that will return me a true value whenever the following method is invoked.
public class ReportService {

    protected boolean readInRawReport(Vector inputFileNameList) {
        boolean found = true;

        for( String inputFileName : inputFileNameList ) {
        ...
        ...
    }
    ...
    return found;
}
I was unit testing the code snippet above using the stub code shown below, unfortunately the test was failed due to NullPointerException happened on inputFileNameList.
public class HibernateReportServiceStubber<T extends HibernateReportService<Object>> {

 private T daoReportService;

 public void readInRawReportReturnTrue() throws Exception {
  PowerMockito.when(this.daoReportService, PowerMockito.method(ReportService.class, "readInRawReport"))
  .withArguments(Mockito.any(Vector.class))
  .thenReturn(true);
 }

 ...
}

This is not supposed to happen when an object is being mock. During the investigation, I found it interesting when I’m tracing the code in debug mode, the code were actually flow into the real method, and inputFileNameList is showing NULL. My first question to myself is why do I need to bother the details implementation since I’m doing mocking? Is that mean Mockito.any() not doing his job? But later I found out I'm actually spying the test object, not mocking. Opps... To prove my justification is correct, I make some changes on the code like this:
  Vector<String> v = new Vector<String>();
  v.add("ASD");

  PowerMockito.when(this.daoReportService, PowerMockito.method(ReportService.class, "readInRawReport"))
  .withArguments(v)
  .thenReturn(true);

Now I can see inputFileNameList is having one element which shows ASD in it. The return value has nothing to do with thenReturn() and this function were totally disabled because the control has already been transfer into the hand of the real method when the test object is being spy. I wonder whether is this the right way to do this? Fortunately, I was so lucky that I manage to find the right way to do this. Thank God. Here is the correct solution on mocking the return value when a test object is being spy is shown below:
  PowerMockito.doReturn(true)
  .when(this.daoReportService, PowerMockito.method(ReportService.class, "readInRawReport"))
  .withArguments(Mockito.any(Vector.class));
This was like an English grammar, tweak from active sentence to a passive sentence.

Wednesday, December 18, 2013

Performing unit test on non-public method with PowerMockito

Recently I’m running a series of unit testing on my own works. I found out that it is quite difficult for me because my code consists of abstract classes, protected fields and protected methods. I’ve been using Java Reflection on this issue before I found the solution on PowerMockito. Somehow, I find it easier to implement it using PowerMockito due to the number of LOC is smaller and also it is much more expensive as I read in this post.

Here is the details implementation on accessing private method through PowerMockito.
objectUnderTest = PowerMockito.spy(new TheRealImplementation());

PowerMockito.doNothing()
            .when(objectUnderTest, PowerMockito.method(TheTargetClass.class, "thePrivateMethod"))
            .withNoArguments();

Assuming TheRealImplementation class is as shown below:
public class TheRealImplementation {

    private void thePrivateMethod() {
        ...
        ...
    }
    ...
}