Sök…


Hur man testar en enkel Spring Boot-applikation

Vi har ett exempel på vårstartprogram som lagrar användardata i MongoDB och vi använder Resttjänster för att hämta data

Först finns det en domänklass, dvs. POJO

@Document
public class User{
    @Id
    private String id;

    private String name;

}

Ett motsvarande arkiv baserat på Spring Data MongoDB

public interface UserRepository extends MongoRepository<User, String> {
}

Sedan vår användarkontroller

@RestController
class UserController {
 
    @Autowired
    private UserRepository repository;
 
    @RequestMapping("/users")
    List<User> users() {
        return repository.findAll();
    }
 
    @RequestMapping(value = "/Users/{id}", method = RequestMethod.DELETE)
    @ResponseStatus(HttpStatus.NO_CONTENT)
    void delete(@PathVariable("id") String id) {
        repository.delete(id);
    }
 
    // more controller methods
}

Och slutligen vår Spring Boot Application

@SpringBootApplication
public class Application {
    public static void main(String args[]){
     SpringApplication.run(Application.class, args);
    }
}

Om, låt oss säga att John Cena, The Rock och TripleHHH var de enda tre användarna i databasen, skulle en begäran till / användare ge följande svar:

$ curl localhost:8080/users
[{"name":"John Cena","id":"1"},{"name":"The Rock","id":"2"},{"name":"TripleHHH","id":"3"}]

För att testa koden kommer vi nu att verifiera att applikationen fungerar

@RunWith(SpringJUnit4ClassRunner.class)   // 1
@SpringApplicationConfiguration(classes = Application.class)   // 2
@WebAppConfiguration   // 3
@IntegrationTest("server.port:0")   // 4
public class UserControllerTest {

    @Autowired   // 5
    UserRepository repository;

    User cena;
    User rock;
    User tripleHHH;

    @Value("${local.server.port}")   // 6
    int port;

    @Before
    public void setUp() {
        // 7
        cena = new User("John Cena");
        rock = new User("The Rock");
        tripleHHH = new User("TripleHH");

        // 8
        repository.deleteAll();
        repository.save(Arrays.asList(cena, rock, tripleHHH));

        // 9
        RestAssured.port = port;
    }

    // 10
    @Test
    public void testFetchCena() {
        String cenaId = cena.getId();

        when().
                get("/Users/{id}", cenaId).
        then().
                statusCode(HttpStatus.SC_OK).
                body("name", Matchers.is("John Cena")).
                body("id", Matchers.is(cenaId));
    }

    @Test
    public void testFetchAll() {
        when().
                get("/users").
        then().
                statusCode(HttpStatus.SC_OK).
                body("name", Matchers.hasItems("John Cena", "The Rock", "TripleHHH"));
    }

    @Test
    public void testDeletetripleHHH() {
        String tripleHHHId = tripleHHH.getId();

        when()
                .delete("/Users/{id}", tripleHHHId).
        then().
                statusCode(HttpStatus.SC_NO_CONTENT);
    }
}

Förklaring

  1. Liksom alla andra SpringJUnit4ClassRunner behöver vi SpringJUnit4ClassRunner så att en applikationskontekst skapas.
  2. @SpringApplicationConfiguration kommentarerna liknar @ContextConfiguration kommentaren genom att den används för att ange vilka applikationskontext (er) som ska användas i testet. Dessutom kommer den att utlösa logik för att läsa Spring Boot-specifika konfigurationer, egenskaper och så vidare.
  3. @WebAppConfiguration måste finnas för att berätta för våren att en WebApplicationContext bör laddas för testet. Det ger också ett attribut för att ange sökvägen till roten till webbapplikationen.
  4. @IntegrationTest används för att berätta för Spring Boot att den inbäddade webbservern bör startas. Genom att tillhandahålla kolonn- eller lika-separerade namnvärdespar kan alla miljövariabler åsidosättas. I det här exemplet "server.port:0" serverns standardportinställning. Normalt börjar servern använda det angivna portnumret, men värdet 0 har en speciell betydelse. När det anges som 0, berättar det för Spring Boot att skanna portarna i värdmiljön och starta servern på en slumpmässig, tillgänglig port. Det är användbart om vi har olika tjänster som upptar olika portar på utvecklingsmaskinerna och build-servern som potentiellt kan kollidera med applikationsporten, i vilket fall applikationen inte kommer att starta. För det andra, om vi skapar flera integrationstester med olika applikationskontekster, kan de också kollidera om testerna körs samtidigt.
  5. Vi har tillgång till applikationens sammanhang och kan använda autowiring för att injicera vilken som helst vårböna.
  6. @Value("${local.server.port}”) kommer att lösas till det faktiska portnumret som används.
  7. Vi skapar några enheter som vi kan använda för validering.
  8. MongoDB-databasen rensas och initialiseras på nytt för varje test så att vi alltid validerar mot ett känt tillstånd. Eftersom testens ordning inte är definierad är chansen stor att testet TestFetchAll () misslyckas om det utförs efter testetDeletetripleHHH () -testet.
  9. Vi instruerar Rest Assured att använda rätt port. Det är ett öppen källkodsprojekt som tillhandahåller en Java DSL för att testa vilsamma tjänster
  10. Test genomförs med hjälp av Rest Assured. vi kan implementera testerna med TestRestTemplate eller någon annan http-klient, men jag använder Rest Assured eftersom vi kan skriva kortfattad dokumentation med RestDocs

Laddar annan yaml [eller egenskaper] -fil eller åsidosätter vissa egenskaper

När vi använder @SpringApplicationConfiguration kommer den att använda konfigurering från application.yml [egenskaper] som i vissa situationer inte är lämpligt. Så för att åsidosätta egenskaperna kan vi använda @TestPropertySource kommentarer.

@TestPropertySource(
        properties = {
                "spring.jpa.hibernate.ddl-auto=create-drop",
                "liquibase.enabled=false"
        }
)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTest{

    // ...

}

Vi kan använda egenskaper attribut för @TestPropertySource att åsidosätta de specifika egenskaper vi vill ha. I exemplet ovan åsidosätter vi egenskapen spring.jpa.hibernate.ddl-auto att create-drop . Och liquibase.enabled till false .

Laddar olika yml-filer

Om du vill helt ladda olika YML fil för test kan du använda platser attribut på @TestPropertySource .

@TestPropertySource(locations="classpath:test.yml")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(Application.class)
public class ApplicationTest{

    // ...

}

Alternativt alternativ

Alternativ 1:

Du kan också ladda olika yml- filer när jag placerar en yml- fil på test > resource

Alternativ 2:

Använda @ActiveProfiles kommentarer

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@ActiveProfiles("somename")
public class MyIntTest{
}

Du kan se att vi använder @ActiveProfiles kommentarer och vi skickar namnet som värdet.

Skapa en fil som heter application-somename.yml och testet laddar den här filen.



Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow