2012-06-20 9 views
8

Der Titel sagt so ziemlich alles. Ich möchte einen traditionellen JUnit-Test einrichten, um die Abhängigkeiten eines Controllers nachzuahmen und Tests gegen Aktionen auszuführen.Unit testet einen Play-Controller mit Mocks

Ich habe festgestellt, dass ich mein Ziel, wie dies erreichen kann:

public class AccountsControllerTest { 
    private controllers.Accounts accountsController; 

    @Test 
    public void test() { 
     running(fakeApplication(), new Runnable() { 
      public void run() { 
       accountsController = new controllers.Accounts(); 
       accountsController.setAccountsWorkflow(mock(workflow.Accounts.class)); 
      } 
     }); 
    } 
} 

Das offensichtliche Problem hier ist, dass ich meine Klasse im Test bin Instanziieren und Mock Abhängigkeiten von dem Testverfahren der Injektion selbst, wenn ich sollte das in der setup() Methode tun. Es scheint, dass die setup() Methode nutzlos ist, wenn ich meinen Controller auf traditionelle Weise testen werde.

Natürlich kann ich Controller testen the way Play recommends, aber meine Anwendung ist abhängig von einem externen SOAP-Web-Service, so brauche ich Unit-Tests, um zu zeigen, dass unser Code funktioniert, wenn ihre Server heruntergefahren sind.

Also, was ist der beste Weg zum Unit-Test eines Play-Controllers mit Mocks unter Ausnutzung der setup() und teardown() Methoden?

bearbeiten

Ich weiß, ich bin etwas Wissen hier unter der Annahme, so dass für diejenigen, die nicht bewusst sind, Controller Instanziierung in einem Unit-Test in einer running() Funktion oder Wiedergabe gewickelt werden muss! Es wird eine Laufzeitausnahme ausgelöst, die besagt, dass keine Anwendung gestartet wurde.

+0

http://www.joergviola.de/blog/2012/06/04/page-driven-functional-tests-for-play-2-dot-0/ ist eine nette Möglichkeit zum Testen, hat aber immer noch das Scheinproblem. Sie könnten versuchen, den Test ohne fakeApplication auszuführen. Siehe http://stackoverflow.com/questions/10381354/how-to-manipulate-session-request-and-response-for-test-in-play2-0 – niels

+0

http://stackoverflow.com/a/10114621/89509 –

+0

Danke für das Beispiel. Wie konnten Sie den Controller außerhalb der 'running'-Funktion instanziieren? Diese Einschränkung hindert mich daran, JUnits Setup-Methode zu nutzen, so dass ich keine Mocks für jede Testmethode einrichten muss. Ihr Beispiel zeigt dies nicht wirklich. – Samo

Antwort

1

Sie können dies mit Mockito und Play's FakeApplication erreichen und die statische Http.Context Variable setzen.

Auf diese Weise können Sie den Test wie alle anderen JUnit-Test schreiben.

Beispiel:

... 
import static play.test.Helpers.status; 
import play.test.FakeApplication; 
import play.test.Helpers; 
import play.mvc.Http; 
import play.mvc.Result; 
... 

@RunWith(MockitoJUnitRunner.class) 
public class ApplicationTest { 

    public static FakeApplication app; 

    @Mock 
    private Http.Request request; 

    @BeforeClass 
    public static void startApp() { 
     app = Helpers.fakeApplication(); 
     Helpers.start(app); 

    } 

    @Before 
    public void setUp() throws Exception { 
     Map<String, String> flashData = Collections.emptyMap(); 
     Http.Context context = new Http.Context(request, flashData, flashData); 
     Http.Context.current.set(context); 
    } 

    @Test 
    public void testIndex() { 
     final Result result = Application.index(); 
     assertEquals(play.mvc.Http.Status.OK, status(result)); 
    } 

    @AfterClass 
    public static void stopApp() { 
     Helpers.stop(app); 
    } 
+0

Ich wusste nicht, dass Sie den aktuellen Http.Context so einstellen könnten - das ist cool; Vielen Dank. – duma

+0

Ich habe festgestellt, dass durch Setzen von 'Http.Context.current.set (context);' meine nachfolgenden Tests auf Anwendung fehlgeschlagen. Daher müssen Sie den Kontext in einer @AfterClass auf den ursprünglichen Zustand zurücksetzen. –

Verwandte Themen