Поиск…


Как протестировать приложение Spring Spring

У нас есть пример загрузки Spring, который хранит данные пользователя в MongoDB, и мы используем службы Rest для получения данных

Сначала есть класс домена, то есть POJO

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

    private String name;

}

Соответствующий репозиторий на основе Spring Data MongoDB

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

Затем наш пользовательский контроллер

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

И, наконец, наше приложение для загрузки Spring

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

Если, скажем так, что John Cena, The Rock и TripleHHH были единственными тремя пользователями в базе данных, запрос / пользователям дал бы следующий ответ:

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

Теперь, чтобы проверить код, мы проверим, работает ли приложение

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

объяснение

  1. Как и любой другой тест Spring, нам нужен SpringJUnit4ClassRunner чтобы создать контекст приложения.
  2. @SpringApplicationConfiguration аналогично аннотации @ContextConfiguration в том, что оно используется для указания того, какой прикладной контекст (ы), который должен использоваться в тесте. Кроме того, он будет запускать логику для чтения определенных конфигураций Spring Spring, свойств и т. Д.
  3. @WebAppConfiguration должен присутствовать, чтобы сообщить Spring, что для WebApplicationContext должен быть загружен WebApplicationContext . Он также предоставляет атрибут для указания пути к корню веб-приложения.
  4. @IntegrationTest используется, чтобы сообщить Spring Boot, что должен быть запущен встроенный веб-сервер. Предоставляя пары (пары) имени и значения, разделенные двоеточием или равным, любая переменная среды может быть переопределена. В этом примере "server.port:0" переопределит настройку порта по умолчанию сервера. Обычно сервер будет использовать указанный номер порта, но значение 0 имеет особое значение. Когда указано как 0, он сообщает Spring Boot сканировать порты в среде хоста и запускать сервер на случайном доступном порту. Это полезно, если у нас есть разные службы, занимающие разные порты на машинах разработки и сервере сборки, которые потенциально могут столкнуться с портом приложения, и в этом случае приложение не запустится. Во-вторых, если мы создадим несколько тестов интеграции с различными контекстами приложений, они могут также столкнуться, если тесты выполняются одновременно.
  5. У нас есть доступ к контексту приложения и вы можете использовать autowiring для ввода любого компонента Spring.
  6. @Value("${local.server.port}”) будет разрешен фактический номер порта, который используется.
  7. Мы создаем некоторые объекты, которые мы можем использовать для проверки.
  8. База данных MongoDB очищается и повторно инициализируется для каждого теста, чтобы мы всегда проверяли достоверное состояние. Поскольку порядок тестов не определен, есть вероятность, что тест testFetchAll () завершится неудачно, если он выполняется после теста testDeletetripleHHH ().
  9. Мы рекомендуем Rest Assured использовать правильный порт. Это проект с открытым исходным кодом, который предоставляет Java DSL для тестирования остающихся услуг
  10. Тесты выполняются с помощью Rest Assured. мы можем реализовать тесты с помощью TestRestTemplate или любого другого http-клиента, но я использую Rest Assured, потому что мы можем писать краткую документацию с помощью RestDocs

Загрузка другого файла yaml [или свойств] или переопределение некоторых свойств

Когда мы используем @SpringApplicationConfiguration он будет использовать конфигурацию из application.yml [properties], которая в определенной ситуации не подходит. Поэтому для переопределения свойств мы можем использовать аннотацию @TestPropertySource .

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

    // ...

}

Мы можем использовать атрибут свойств @TestPropertySource для переопределения конкретных свойств, которые мы хотим. В приведенном выше примере мы переопределяем свойство spring.jpa.hibernate.ddl-auto для create-drop . И liquibase.enabled to false .

Загрузка другого файла yml

Если вы хотите полностью загрузить другой файл yml для теста, вы можете использовать атрибут местоположений на @TestPropertySource .

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

    // ...

}

Альтернативно варианты

Опция 1:

Вы также можете загрузить другой файл yml, поместив yml- файл в test > resource каталог test > resource

Вариант 2:

Использование аннотации @ActiveProfiles

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

Вы можете видеть, что мы используем аннотацию @ActiveProfiles и мы передаем значение somename как значение.

Создайте файл под названием application-somename.yml и тест загрузит этот файл.



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow