2016-04-20 8 views
2

spotten, wenn ich versuche, folgende Methode zu verspotten für den JUnit-Test (Methode Remote EJB Aufruf für Business-Logik verwendet), gibt es javax.naming.NoInitialContextExceptionWie Initial Konstruktor in Unit-Tests

private void someMethod(int id1, int id2, HashMap map){ 
    ......some code........ 

    Context ctx = new InitialContext(); 
    Object ref = ctx.lookup("com.java.ejbs.MyEJB"); 

    EJBHome ejbHome = (EJBHome)PortableRemoteObject.narrow(ref, EJBHome.class); 
    EJBBean ejbBean = (EJBBean)PortableRemoteObject.narrow(ejbHome.create(), EJBBean.class); 
    ejbBean.someMethod(id1,name); 

    .......some code.......} 

Meine Einheit Test für obige Verfahren

@Test 
public void testsomeMethod() throws Exception { 

    .......setting initial code... 
    //Mock context and JNDI 

    InitialContext cntxMock = PowerMock.createMock(InitialContext.class); 
    PowerMock.expectNew(InitialContext.class).andReturn(cntxMock); 
    expect(cntxMock.lookup("com.java.ejbs.MyEJB")).andReturn(refMock);    

    ..........some code.......... 

    PowerMock.replayAll(); 
    Whitebox.invokeMethod(ObjectOfsomeMethodClass, "someMethod", id1, id2, map); 


} 

wenn die Whitebox.invokeMethod (ObjectOfsomeMethodClass, "irgendeinemethode", ID1, ID2, Karte) Methode ruft es gibt Ausnahme folgen.

javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial 
at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:645) 
at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:288) 
at javax.naming.InitialContext.getURLOrDefaultInitCtx(InitialContext.java:325) 
at javax.naming.InitialContext.lookup(InitialContext.java:392) 

glaube ich, obwohl wir den Context in Testmethode verspotten, ist es nicht das Mock-Objekt nicht verwendet beim Aufruf Whitebox.invokeMethod (ObjectOfsomeMethodClass, "irgendeinemethode", ID1, ID2, Karte) Verfahren, statt dessen versucht es, den Kontext aufzurufen ctx = new InitialContext(); Methode in der ursprünglichen Methode (someMethod).

+0

Sie könnten eine in-memory InitialContextFactory in Ihre Tests hinzufügen, Beispiel: http://StackOverflow.com/questions/3461310 –

Antwort

1

Sie können Ihren Code umgestalten und die Initialisierung des Kontexts in der neuen Methode extrahieren.

private void someMethod(int id1, int id2, HashMap map){ 
    ......some code........ 

    Context ctx = getInitialContext(); 
    Object ref = ctx.lookup("com.java.ejbs.MyEJB"); 

    EJBHome ejbHome = (EJBHome)PortableRemoteObject.narrow(ref, EJBHome.class); 
    EJBBean ejbBean = (EJBBean)PortableRemoteObject.narrow(ejbHome.create(), EJBBean.class); 
    ejbBean.someMethod(id1,name); 

    .......some code.......} 

Ihre Test-Code wird in etwa so sein:

Context mockContext = mock(Context.class); 
doReturn(mockContext).when(yourclass).getInitalContext(); 
...... some code.... 
+1

S.Stavreva danke für Ihre Antwort, aber ich werde Junit Test für bestehende Methode schreiben, daher kann ich die eigentliche Methodenimplementierung nicht ändern. – Anushka

4

Handgemachte

Wie InitialContext doc sagt, können Sie Ihre eigene Fabrik für InitialContext Objekte zur Verfügung stellen kann, mit java.naming.factory.initial Systemeigenschaft. Wenn der Code im Anwendungsserver ausgeführt wird, wird die Systemeigenschaft vom Server festgelegt. In unseren Tests stellen wir eine eigene Implementierung von JNDI zur Verfügung.

Hier ist meine Mockito einzige Lösung: Ich habe eine benutzerdefinierte InitialContextFactory Klasse definiert, die eine Schein von InitialContext zurückgibt. Sie passen den Schein so an, wie Sie möchten, wahrscheinlich, um mehr Mocks auf lookup Aufrufe zurück zu geben.

public class PlainTest { 
    @Mock InitialContextFactory ctx; 
    @InjectMocks Klasa1 klasa1; 

    public static class MyContextFactory implements InitialContextFactory 
    { 
    @Override 
    public Context getInitialContext(Hashtable<?, ?> environment) throws NamingException { 
     ConnectionFactory mockConnFact = mock(ConnectionFactory.class); 
     InitialContext mockCtx = mock(InitialContext.class); 
     when(mockCtx.lookup("jms1")).thenReturn(mockConnFact); 
     return mockCtx; 
    } 
    } 

    @Before 
    public void setupClass() throws IOException 
    { 
    MockitoAnnotations.initMocks(this); 
    System.setProperty("java.naming.factory.initial", 
     this.getClass().getCanonicalName() + "$MyContextFactory"); 
    } 

Frühling (hinzugefügt von bearbeiten)

Wenn Sie nichts dagegen haben, Spring Framework für Testzwecke nutzen, hier ist ihre einfache Lösung: SimpleNamingContextBuilder:

SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder(); 
DataSource ds = new DriverManagerDataSource(...); 
builder.bind("java:comp/env/jdbc/myds", ds); 
builder.activate(); 

Es ist ok um es in @Before oder @BeforeClass zu setzen. Nach activate() werden die Jndi-Daten vom Spring-Dummy gezogen.