title: Mocking Hibernate's SessionFactory using EasyMock
body: <p>I am trying to write a unit test for the following class:</p>
  
  <pre><code>@Transactional
  public class EditorHelper {
  
  private static SessionFactory sf;
  
  static {        
      ClassPathResource hbr = new ClassPathResource("hibernate.cfg.xml");
      File hbCfg = null;
  
      try {
          hbCfg = hbr.getFile();
      } catch (IOException e) {
          e.printStackTrace();
      }
      if (hbCfg != null) {
          sf = new AnnotationConfiguration().configure(hbCfg).buildSessionFactory(); // &lt;-- Stack trace points here
      }
  }
  public static void setSf(SessionFactory sf) {
      EditorHelper.sf = sf;
  }
  }
  </code></pre>
  
  <p>There are some other methods, but this setup code is what's relevant to my question.  In my unit test, I want to mock (using EasyMock) the <code>SessionFactory</code> object <code>sf</code>, as well as the <code>Session</code> and <code>Transaction</code> objects it will return:</p>
  
  <pre><code>public class EditorTest {
  
      private SessionFactory sf;
      private Session s;
      private Transaction tx;
      private Long id = 1L;
      private String idStr = id.toString();
  
      @Before
      public void setUp() {
  
          sf = EasyMock.createMock(SessionFactory.class);
          s = EasyMock.createMock(Session.class);
          tx = EasyMock.createMock(Transaction.class);
  
          EditorHelper.setSf(sf); // &lt;-- Stack trace points here
  
          EasyMock.expect(sf.getCurrentSession()).andReturn(s);
          EasyMock.expect(s.beginTransaction()).andReturn(tx);
      }
  // Tests go here
  }
  </code></pre>
  
  <p>When I try to run this with JUnit, I get the following error:</p>
  
  <pre><code>java.lang.NoSuchFieldError: INSTANCE
      at org.hibernate.type.BasicTypeRegistry.&lt;init&gt;(BasicTypeRegistry.java:94)
      at org.hibernate.type.TypeResolver.&lt;init&gt;(TypeResolver.java:59)
      at org.hibernate.cfg.Configuration.&lt;init&gt;(Configuration.java:250)
      at org.hibernate.cfg.Configuration.&lt;init&gt;(Configuration.java:302)
      at org.hibernate.cfg.AnnotationConfiguration.&lt;init&gt;(AnnotationConfiguration.java:87)
      at com.mypkg.helper.EditorHelper.&lt;clinit&gt;(EditorHelper.java:38)
      at com.mypkg.model.EditorTest.setUp(EditorTest.java:29)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
      at java.lang.reflect.Method.invoke(Unknown Source)
      at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
      at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
      at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
      at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:76)
      at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:50)
      at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
      at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
      at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
      at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
      at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
      at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
      at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:49)
      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)
  </code></pre>
  
  <p>There is no public <code>INSTANCE</code> variable on <code>sf</code> that I can see.  I'm new to EasyMock, so I think my question is: what should I tell my mock to return for <code>INSTANCE</code>, and how do I tell it to do that?  I don't know why the <code>SessionFactory</code> setup code is being called by <code>setSf()</code> at all, so that's another mystery.  The more general question is: how should I mock up a SessionFactory object anyway?</p>
  
  <h2>Update</h2>
  
  <p>I figured out that catching the exception without doing anything will work just fine.  I have changed my <code>EditorHelper</code> class as follows:</p>
  
  <pre><code>@Transactional
  public class EditorHelper {
  
  private static SessionFactory sf;
  
  static {    
  
  ...
  
      if (hbCfg != null) {
          try { // New try block lets the initializaiton fail
              sf = new AnnotationConfiguration().configure(hbCfg).buildSessionFactory();
          } catch (NoSuchFieldError e) {
              e.printStackTrace();
          }
      }
  ...
  </code></pre>
  
  <p>Once this static block completes, I can set the <code>SessionFactory</code> member to point to my mock object and everything works from there.</p>