2009-09-11 5 views
1

J'ai implémenté un serveur RMI et maintenant je voulais tester si la méthode pour démarrer et arrêter ce serveur est correctement implémentée, en utilisant un test JUnit.Problème lors du test unitaire de la méthode d'arrêt de mon serveur RMI

Voici le code de mon serveur RMI (simplifié):

public void startServer() { 
    try { 
     ... 
     registry = LocateRegistry.createRegistry(serverPort); 
     registry.rebind("foobar", myRemoteObject); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

public void stopServer() { 
    try { 
     registry.unbind("foobar"); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

Maintenant, je veux faire un test JUnit pour vérifier si le startServer() et stopServer() fonctionnent correctement.

Ainsi, j'ai mis ce simple test JUnit:

private boolean isRunning(int port) { 
    boolean portTaken = false; 
    ServerSocket socket = null; 
    try { 
     socket = new ServerSocket(port); 
     // If we have succesfully created the ServerSocket, then it means that the port is available... 
    } catch (IOException e) { 
     portTaken = true; 
     if (socket != null) { 
      try { 
       socket.close(); 
      } catch (IOException e2) { 
      } 
     } 
    } 
    return portTaken; 
} 

@Test 
public void testStartAndStopServer() { 
    MyRMIServer server = new MyRMIServer(); 
    assertNotNull(server); 
    int port = server.getServerPort(); 
    assertTrue(port != -1); 
    // Check if the current server is NOT running. 
    assertFalse(isRunning(port)); 
    // Start the server and then check if it is running. 
    server.startServer(); 
    assertTrue(isRunning(port)); 
    // Now stop the server... 
    server.stopServer(); 
    assertFalse(isRunning(port)); 
} 

Mon problème est que la dernière assert n'est pas valide. Si j'imprime la pile dans la méthode isRunning(), j'obtiens l'erreur java.net.BindException: Address already in use: JVM_Bind.

Cela signifie que le port est toujours utilisé, donc je suppose que mon stopServer() n'est pas correct. Qu'est-ce que je me suis trompé?

Notez que si j'utilise la méthode registry.list() avant et après avoir appelé ma méthode stopServer(), je vois:

BEFORE: foobar 
AFTER: (nothing) 

Edit:

J'ai aussi modifié mon stopServer() au sujet d'une solution expliquée here:

public void stopServer() { 
    try { 
     registry.unbind("foobar"); 
     UnicastRemoteObject.unexportObject(myRemoteObject, true); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

mais cela ne résout pas mon problème ...

Répondre

0

D'abord, j'aurais tendance à éviter les blocs d'exception vides, même dans les cas "impossible".

try { 
      socket.close(); 
    } catch (IOException e2) { 
    } 

juste de manière concenvable il y a une exception.

Ma (plutôt sauvage) supposition, c'est que vous pourriez avoir un problème de synchronisation. Peut-être que l'infrastructure réseau prend un peu de temps pour remarquer que le socket est fermé. Est-ce que dormir pendant une seconde ou deux avant l'assertion finale le réparer?

+0

1. Oui, dans mon code complet, aucun bloc d'exception est vide;) C'était juste pour simplifier le code ici. 2. J'ai essayé de mettre un Thread.sleep (jusqu'à 5000ms) juste après server.stopServer() ;, mais cela n'aide pas :( – romaintaz

0

Je pense que vous devez exporter le registre. Essayez:

public void stopServer() { 
    try { 
     registry.unbind("foobar"); 
     UnicastRemoteObject.unexportObject(registry, true); 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
} 

Cependant, one source réclamations vous ne pouvez pas libérer le port jusqu'à la sortie JVM. Je ne sais pas si c'est vrai ou non (je ne l'ai pas essayé), mais le fait de ne pas exporter le registre est un pas dans la bonne direction.

1

J'ai eu le même problème et a fini par modifier mon code serveur afin que la méthode de démarrage regarderait essentiellement comme (notez l'appel à getRegistry et rebindaprès la prise qui récupéreront le registre si elle était déjà là) :

public void startServer() { 
    try { 
     ... 
     registry = LocateRegistry.createRegistry(serverPort); 
    } catch (RemoteException e) { 
    } 
    LocateRegistry.getRegistry(port); 
    registry.rebind("foobar", myRemoteObject); 
} 
Questions connexes