Szukaj…


Jak przetestować prostą aplikację Spring Boot

Mamy przykładową aplikację Spring boot, która przechowuje dane użytkownika w MongoDB i do odzyskiwania danych używamy usług Rest

Najpierw jest klasa domeny, tj. POJO

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

    private String name;

}

Odpowiednie repozytorium oparte na Spring Data MongoDB

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

Następnie nasz kontroler użytkowników

@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
}

I wreszcie nasza aplikacja Spring Boot

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

Jeśli, powiedzmy, że John Cena, The Rock i TripleHHH byli jedynymi trzema użytkownikami w bazie danych, zapytanie do / użytkowników dałoby następującą odpowiedź:

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

Teraz, aby przetestować kod, sprawdzimy, czy aplikacja działa

@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);
    }
}

Wyjaśnienie

  1. Jak każdy inny test oparty na wiośnie, potrzebujemy SpringJUnit4ClassRunner aby SpringJUnit4ClassRunner kontekst aplikacji.
  2. Adnotacja @SpringApplicationConfiguration jest podobna do adnotacji @ContextConfiguration , ponieważ służy do określania kontekstu aplikacji, który powinien zostać użyty w teście. Dodatkowo uruchomi logikę do odczytywania określonych konfiguracji, właściwości itd. Spring Boot.
  3. @WebAppConfiguration muszą być obecne, aby powiedzieć, że wiosna WebApplicationContext powinien być załadowany do testu. Zapewnia także atrybut do określania ścieżki do katalogu głównego aplikacji internetowej.
  4. @IntegrationTest służy do poinformowania Spring Boot, że należy uruchomić wbudowany serwer internetowy. Zapewniając pary nazwa-wartość rozdzielone dwukropkami lub równorzędne, można zastąpić dowolną zmienną środowiskową. W tym przykładzie "server.port:0" zastąpi domyślne ustawienie portu serwera. Normalnie serwer zaczynałby używać określonego numeru portu, ale wartość 0 ma specjalne znaczenie. Po określeniu jako 0, Spring Boot skanuje porty w środowisku hosta i uruchamia serwer na losowo dostępnym porcie. Jest to przydatne, jeśli mamy różne usługi zajmujące różne porty na komputerach programistycznych i serwer kompilacji, które mogą potencjalnie kolidować z portem aplikacji, w którym to przypadku aplikacja się nie uruchomi. Po drugie, jeśli utworzymy wiele testów integracji z różnymi kontekstami aplikacji, mogą one również kolidować, jeśli testy są wykonywane jednocześnie.
  5. Mamy dostęp do kontekstu aplikacji i możemy użyć automatycznego okablowania, aby wstrzyknąć dowolną fasolę wiosenną.
  6. Wartość @Value("${local.server.port}”) zostanie rozstrzygnięta na rzeczywisty numer używanego portu.
  7. Tworzymy niektóre podmioty, które możemy wykorzystać do weryfikacji.
  8. Baza danych MongoDB jest czyszczona i ponownie inicjowana dla każdego testu, dzięki czemu zawsze sprawdzamy poprawność względem znanego stanu. Ponieważ kolejność testów nie jest zdefiniowana, istnieje prawdopodobieństwo, że test testFetchAll () zakończy się niepowodzeniem, jeśli zostanie wykonany po teście testDeletetripleHHH ().
  9. Poinstruujemy firmę Rest Assured, aby używała właściwego portu. Jest to projekt typu open source, który zapewnia Java DSL do testowania usług restful
  10. Testy są wdrażane przy użyciu Rest Assured. możemy zaimplementować testy przy użyciu TestRestTemplate lub dowolnego innego klienta HTTP, ale używam Rest Assured, ponieważ możemy pisać zwięzłą dokumentację przy użyciu RestDocs

Ładowanie innego pliku yaml [lub właściwości] lub zastępowanie niektórych właściwości

Kiedy użyjemy @SpringApplicationConfiguration , użyje konfiguracji z application.yml [właściwości], co w niektórych sytuacjach nie jest właściwe. Aby więc zastąpić właściwości, możemy użyć adnotacji @TestPropertySource .

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

    // ...

}

Możemy użyć atrybutu właściwości @TestPropertySource aby zastąpić określone właściwości, które chcemy. W powyższym przykładzie nadpisujemy właściwość spring.jpa.hibernate.ddl-auto aby create-drop . I liquibase.enabled na false .

Ładowanie innego pliku yml

Jeśli chcesz całkowicie załadować inny plik yml do testu, możesz użyć atrybutu położenia na @TestPropertySource .

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

    // ...

}

Alternatywnie opcje

Opcja 1:

Możesz także załadować inny plik yml , umieszczając plik yml w katalogu test > resource

Opcja 2:

Korzystanie z adnotacji @ActiveProfiles

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

Można zobaczyć używamy @ActiveProfiles adnotacji i jesteśmy przekazując somename jako wartość.

Utwórz plik o nazwie application-somename.yml a test załaduje ten plik.



Modified text is an extract of the original Stack Overflow Documentation
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow