5 Stimmen

Wie JMockIt System.getenv(String)?

Was ich im Moment habe

Ich habe eine Singleton-Instanz eines Drittanbieters, auf die meine zu testende Klasse angewiesen ist, und dieses Singleton verwendet System.getenv(String) in seinem Konstruktor. Ist es möglich, diesen Aufruf zu simulieren?

Ich habe dies versucht

JMockIt Beispiel

    new Expectations()
    {

        System mockedSystem;
        {
            System.getenv( "FISSK_CONFIG_HOME" ); returns( "." );
        }
    };

Aber es gibt mir eine EXCEPTION_ACCESS_VIOLATION und bringt die JVM zum Absturz.

Gibt es eine andere Möglichkeit, eine Systemumgebungsvariable für einen Unit-Test zu setzen?

15voto

Rogério Punkte 15717

In diesem Fall müssen Sie partielles Mocking verwenden, damit JMockit nicht alles in der Klasse System umdefiniert. Der folgende Test wird bestehen:

   @Test
   public void mockSystemGetenvMethod()
   {
      new Expectations()
      {
         @Mocked("getenv") System mockedSystem;

         {
            System.getenv("envVar"); returns(".");
         }
      };

      assertEquals(".", System.getenv("envVar"));
   }

Ich werde bald eine Verbesserung implementieren, damit solche Probleme beim Mocking von JRE-Klassen nicht mehr auftreten. Sie sollte in Version 0.992 oder 0.993 verfügbar sein.

3voto

PowerMock scheint in der Lage zu sein, Systemklassen nachzubilden.

Ihre andere Option (vorausgesetzt, Sie testen die API des Drittanbieters nicht als Einheit) ist die Erstellung einer for Fassade die API eines Drittanbieters, die über eine schöne, einfach nachahmbare Schnittstelle verfügt, und lassen Sie Ihre Testklassen diese verwenden, anstatt die reale Sache.

Oh, JMockIt unterstützt dies auch: Paket Playtest;

import static org.junit.Assert.*;

import mockit.*;
import mockit.integration.junit4.JMockit;

import org.junit.*;
import org.junit.runner.RunWith;

@RunWith(JMockit.class)
public class JMockItTest {

 @Test
 public void mockSystemGetEnv() {
  Mockit.setUpMocks(MockSystem.class); 

  assertEquals("Bye", System.getenv("Hello"));

 }

 @MockClass(realClass = System.class)
 public static class MockSystem {
  @Mock
  public static String getenv(String str) {
   return "Bye";
  }
 }

}

2voto

Aaron Digulla Punkte 308693

Man kann die Umgebung nicht ändern, aber man kann den Zugang zu ihr ändern: Wickeln Sie einfach den Aufruf von System.getenv() in einer Methode oder einer Hilfsklasse und spottet dann darüber.

[EDIT] Jetzt ist Ihr Problem, wie Sie den Code Ihrer Drittanbieter-Bibliothek ändern. Die Lösung besteht darin, einen Java-Decompiler zu verwenden und die Klasse zu korrigieren. Wenn Sie wollen, können Sie auch einen Feature Request einreichen. Fügen Sie die neue Klasse zu Ihrer Testsuite hinzu. Das sollte Ihre IDE dazu bringen, die Klasse für die Tests zu finden.

Da der Testcode nicht in die Produktion einfließt, können Sie Ihre Tests ausführen und der Produktionscode verwendet die Originalbibliothek.

1voto

brianegge Punkte 28043

Vor einiger Zeit wollte ich Test System.exit und fand eine Lösung, indem er eine benutzerdefinierter SecurityManager . Sie können den Aufruf und das Argument des Aufrufs überprüfen, aber mit dieser Methode können Sie den Rückgabewert des Aufrufs nicht nachahmen.

0voto

Alfergon Punkte 5177

Ein Update zur Antwort von @Rogério.

In meinem Fall mit JMockit 1.25 musste ich es mit der MockUp API machen:

@Test
public void mockSystemGetenvMethod(){
    new MockUp<System>()
    {
        @Mock
        public String getenv(final String string) {
            return "";
        }
    };

    assertEquals(".", System.getenv("envVar"));
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X