2014-10-15 15 views
6

Qualcuno sa come aggiungere una risorsa di test (ad esempio una che è solo a scopo di test e non aggiunta nel metodo run() dell'app)?Test integrato Dropwizard con TestResource

Ecco un esempio:

public class MyTest { 
    @ClassRule 
    public static final DropwizardAppRule<TestConfiguration> RULE = 
      new DropwizardAppRule<TestConfiguration>(MyApp.class, "my-app-config.yaml"); 


    @BeforeClass 
    public static void setUpBeforeClass() throws Exception 
    { 
     MyTest.RULE.getEnvironment().jersey().register(new JustForTestingResource()); 
    } 


    @Test 
    public final void testTestResource() 
    { 
     Client client = new Client(); 

     ClientResponse response = client.resource(
      String.format("http://localhost:%d/rest/v1/test", RULE.getLocalPort())) 
      .get(ClientResponse.class); 

     assertThat(response.getStatus(), is(200)); 
    } 
} 

e

public class JustForTestingRessource { 


    @GET 
    @Path("test") 
    @Produces(MediaType.APPLICATION_JSON) 
    public Response getInTestResource() 
    { 
     return Response.status(Status.OK).type(MediaType.TEXT_PLAIN).entity("get @Path(\"test\") is ok").build(); 
    } 
} 

Il mio problema è che la risorsa aggiunto non viene aggiunto e ottengo risorsa non trovato 404 risposta di errore. Sembra che io stia registrando la nuova risorsa dopo la pubblicazione delle risorse e non ci sia alcun aggiornamento all'interno di Dropwizard dopo l'avvio.

Non desidero estendere la mia classe di applicazione e non desidero inserire il codice di test nel mio codice applicazione reale. Qualcuno sa come registrare la risorsa di test senza registrarla nel metodo run() dell'applicazione?

Questo funziona, ma è necessaria una nuova classe:

public class TestService extends MyService{ 


    @Override 
    public void run(
     TestConfigurationconfiguration, 
     Environment environment) throws ClassNotFoundException 
    {  
     environment.jersey().register(new JustForTestingRessource()); 
     super.run(configuration,environment); 
    } 

} 

Chiamata in JUnit come già noto:

@ClassRule 
public static DropwizardAppRule<TestConfiguration> RULE = 
     new DropwizardAppRule<TestConfiguration>(TestService.class, "my-app-config.yaml"); 
+0

Qualcosa di simile RULE.addRessource (...) sarebbe nice ... – user3280180

risposta

5

Modifica: rimozione della risposta precedente perché non risolveva il problema nel modo in cui si voleva farlo.

Ho individuato il codice di avvio dell'ambiente e ho compreso il motivo per cui la registrazione di un controller non lo rendeva disponibile perché il jetty era già stato avviato. Se fermate il molo, registrate il controller e riavviate il molo, la vostra risorsa sarà disponibile e potrete utilizzarla nel vostro test.

@BeforeClass 
public static void setUpBeforeClass() throws Exception 
{ 
    MyTest.RULE.environment.applicationContext.stop() 
    MyTest.RULE.environment.jersey().register(new JustForTestingResource()) 
    MyTest.RULE.environment.applicationContext.start() 
} 
+0

Sì, ma poi ho anche Testcode aggiuntivo nella mia applicazione. Per evitare che sia ancora meglio creare una classe che estenda MyApplication e sovrascrivi run() come ho menzionato sopra. Ma ho chiesto una soluzione migliore aggiungendo una risorsa solo nella TestClass, e questo è il motivo per cui non posso essere d'accordo con la tua soluzione. – user3280180

+0

Puoi approfondire perché tre righe di codice specifiche per il controllo di una variabile di ambiente sono un'opzione inaccettabile? – th3morg

+0

Evito Testcode in LiveCode, quindi anche la mia classe TestService estende MyService è una soluzione migliore, perché non ho metodi "just for testing purpose" nella mia applicazione. Con questo metodo run() sovrascritto posso chiaramente separare il mio test- e il codice di riferimento. Con la tua soluzione sarebbe possibile eseguire una configurazione errata all'interno di live * .yml e quindi hai linee di codice solo per il test nella tua applicazione. – user3280180

2

È possibile verificare la stessa risorsa in un contenitore Jersey senza iniziare un completo dw -esempio.

Controllare il "Testing Resources" section.

import static org.fest.assertions.api.Assertions.assertThat; 
import static org.mockito.Mockito.*; 

public class PersonResourceTest { 

    private static final PeopleStore dao = mock(PeopleStore.class); 

    @ClassRule 
    public static final ResourceTestRule resources = ResourceTestRule.builder() 
     .addResource(new PersonResource(dao)) 
     .build(); 

    private final Person person = new Person("blah", "[email protected]"); 

    @Before 
    public void setup() { 
     when(dao.fetchPerson(eq("blah"))).thenReturn(person); 
     // we have to reset the mock after each test because of the 
     // @ClassRule, or use a @Rule as mentioned below. 
     reset(dao); 
    } 

    @Test 
    public void testGetPerson() { 
     assertThat(resources.client().resource("/person/blah").get(Person.class)) 
      .isEqualTo(person); 
     verify(dao).fetchPerson("blah"); 
    } 
} 
+0

Ho già creato i test delle risorse, ma ho inserito un nuovo filtro e questo è il motivo per cui ho bisogno di "un'istanza dw completa". – user3280180

0

ho avuto il problema simile con la @ClassRule, forse può aiutare a qualcuno ..
Nella mia prova (Groovy) l'invocazione di RULE.getApplication() o getEnvironment() dal metodo @BeforeClass restituito nullo:

def setupSpec() { 
    RULE.application.run() 
} 

shown

java.lang.NullPointerException: Cannot invoke method run() on null object 

Ie RULE.testSupport ha avuto sia l'applicazione nullo sia l'ambiente.

Ho scoperto che la chiamata a RULE.testSupport.prima() poco prima run() risolve l'errore:

def setupSpec() { 
    RULE.testSupport.before() 
    RULE.application.run() 
} 

E poi @AfterClass metodo:

def cleanupSpec() { 
    RULE.testSupport.after() 
} 

o semplicemente usare @Rule invece di @ClassRule e chiamare

def setup() { 
    RULE.application.run() 
} 

all'interno del metodo @Before anziché @BeforeClass.
Anche se sembra strano, forse c'è esiste qualche altra soluzione migliore ..

0

public class TestMain estende principale {

public static void main(String ... args) throws Exception { 
    new TestMain().run(args); 
} 


@Override 
public void initialize(Bootstrap<AppConfiguration> bootstrap) { 
    super.initialize(bootstrap); 
    bootstrap.addBundle(
        new MigrationsBundle<AppConfiguration>() { 
         @Override 
         public DataSourceFactory getDataSourceFactory(
             AppConfiguration configuration) { 
          return configuration.getDataSourceFactory(); 
         } 
        }); 
} 

}

+0

semplicemente estendere la classe principale quindi aggiungere cose specifiche per i test che dovrebbero funzionare, avvio h2 in-mem DB solo per testarlo in questo modo – gli00001