Ghi đè cài đặt Spring-Boot application.properations mặc định trong Junit Test


198

Tôi có một ứng dụng Spring-Boot trong đó các thuộc tính mặc định được đặt trong một application.propertiestệp trong đường dẫn lớp (src / main / resource / application.properies).

Tôi muốn ghi đè một số cài đặt mặc định trong thử nghiệm JUnit của mình với các thuộc tính được khai báo trong một test.propertiestệp (src / test / resource / test.properies)

Tôi thường có Lớp Cấu hình dành riêng cho Bài kiểm tra Junit của mình, ví dụ:

package foo.bar.test;

import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {

}

Trước tiên tôi nghĩ rằng việc sử dụng @PropertySource("classpath:test.properties")trong lớp TestConfig sẽ thực hiện thủ thuật, nhưng các thuộc tính này sẽ không ghi đè cài đặt application.properations (xem Tài liệu tham khảo khởi động mùa xuân - 23. Cấu hình ngoài ).

Sau đó, tôi đã cố gắng sử dụng -Dspring.config.location=classpath:test.propertieskhi gọi thử nghiệm. Điều đó đã thành công - nhưng tôi không muốn đặt thuộc tính hệ thống này cho mỗi lần thực hiện kiểm tra. Vì vậy, tôi đặt nó trong mã

@Configuration
@Import(CoreConfig.class)
@EnableAutoConfiguration
public class TestConfig {

  static {
    System.setProperty("spring.config.location", "classpath:test.properties");
  }

}

điều không may lại một lần nữa không thành công.

Phải có một giải pháp đơn giản về cách ghi đè application.propertiescài đặt trong các bài kiểm tra JUnit test.propertiesmà tôi phải bỏ qua.


Nếu bạn chỉ cần định cấu hình một vài thuộc tính, bạn có thể sử dụng chú thích @DAVEPropertySource mới. stackoverflow.com/a/60941845/8650621
Felipe Desiderati

Câu trả lời:


293

Bạn có thể sử dụng @TestPropertySourceđể ghi đè các giá trị trong application.properties. Từ javadoc của nó:

nguồn thuộc tính thử nghiệm có thể được sử dụng để ghi đè có chọn lọc các thuộc tính được xác định trong nguồn thuộc tính của hệ thống và ứng dụng

Ví dụ:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public class ExampleApplicationTests {

}

2
Đó là nó. Cảm ơn. Thật không may, nó không hoạt động khi được sử dụng trên exampleApplication. Class vì vậy tôi phải đặt nó trên mỗi lớp kiểm tra. Có đúng không?
FrVaBe

1
Nó phải đi đâu đó trong hệ thống phân cấp của lớp thử nghiệm, tức là bạn có thể sử dụng một siêu lớp phổ biến để cấu hình nó qua một số lớp thử nghiệm khác nhau.
Andy Wilkinson

64
Cũng lưu ý rằng @TestPropertySourcecó thể chấp nhận một propertiesđối số để ghi đè lên một số thuộc tính nội tuyến, chẳng hạn như @TestPropertySource(properties = "myConf.myProp=valueInTest"), nó hữu ích trong trường hợp bạn không muốn một tệp thuộc tính hoàn toàn mới.
dyng 3/2/2016

2
Bạn có thể chỉ định nhiều tệp trong một mảng và cả các tệp trên hệ thống tệp (nhưng hãy nhớ rằng chúng có thể không hoạt động trên máy chủ CI):@TestPropertySource(locations={"file:C:/dev/...","classpath:test.properties"})
Adam

8
Lưu ý, điều đó @SpringApplicationConfigurationđã không được chấp nhận và bạn nên sử dụng@SpringBootTest
mrkernelpanic

74

Spring Boot tự động tải src/test/resources/application.properties, nếu các chú thích sau được sử dụng

@RunWith(SpringRunner.class)
@SpringBootTest

Vì vậy, đổi tên test.propertiesđể application.propertiessử dụng cấu hình tự động.

Nếu bạn * chỉ * cần tải tệp thuộc tính (vào Môi trường), bạn cũng có thể sử dụng như sau, như được giải thích ở đây

@RunWith(SpringRunner.class)
@ContextConfiguration(initializers = ConfigFileApplicationContextInitializer.class) 

[ Cập nhật: Ghi đè một số thuộc tính để thử nghiệm ]

  1. Thêm src/main/resources/application-test.properties.
  2. Chú thích lớp kiểm tra với @ActiveProfiles("test").

Điều này tải application.propertiessau đó application-test.properties thuộc tính vào bối cảnh ứng dụng cho trường hợp thử nghiệm, theo quy tắc được xác định ở đây .

Bản trình diễn - https://github.com/moharn82/so-spring-boot-testprops


1
Không chắc chắn nếu có hai application.propertiestệp trên đường dẫn lớp là một ý tưởng tốt (một trong src/main/resourcesvà một trong src/test/resources). Ai đảm bảo rằng cả hai sẽ được thực hiện và cái nào sẽ được thực hiện đầu tiên?
FrVaBe

3
@FrVaBe Mùa xuân sẽ đảm bảo điều đó! Thuộc tính hồ sơ chính luôn được tải. Sau đó trong giai đoạn thử nghiệm, các thuộc tính thử nghiệm được tải, thêm / ghi đè các thuộc tính mới / hiện có. Nếu bạn không thích giữ hai tập tin cùng tên, sau đó bạn có thể thêm application-test.propertiesvào src/main/resourcesvà chỉ định testnhư hồ sơ cá nhân hoạt động trong trường hợp thử nghiệm.
Mohamel

7
Mùa xuân không cho một sự đảm bảo. Công cụ xây dựng sẽ sử dụng các tài nguyên kiểm tra có lợi cho các tài nguyên chính trong các thử nghiệm. Nhưng trong trường hợp của một ứng dụng thử nghiệm. Các ứng dụng chính thì các ứng dụng chính sẽ bị bỏ qua. Đó không phải là điều tôi muốn bởi vì cái chính chứa một vài giá trị mặc định hữu ích và tôi chỉ cần ghi đè một số trong số chúng trong quá trình kiểm tra (và tôi không muốn sao chép toàn bộ tệp trong phần kiểm tra). Xem ở đây .
FrVaBe

6
Bạn đúng, chỉ các thuộc tính được xác định trong src/test/resources/application.propertiesđược tải trong giai đoạn thử nghiệm, src/main/resources/application.propertiesbị bỏ qua.
Mohamel

11
Nếu bạn không sử dụng hồ sơ cho đến nay bạn không cần một hồ sơ "kiểm tra" chuyên dụng. Chỉ cần đặt tên cho các thuộc tính thử nghiệm của bạn application-default.propertiesvà chúng sẽ được xem xét bởi vì bạn đang tự động chạy hồ sơ "mặc định" (nếu không khai báo bất kỳ cái nào khác).
FrVaBe

65

Bạn cũng có thể sử dụng các chú thích meta để bên ngoài cấu hình. Ví dụ:

@RunWith(SpringJUnit4ClassRunner.class)
@DefaultTestAnnotations
public class ExampleApplicationTests { 
   ...
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@SpringApplicationConfiguration(classes = ExampleApplication.class)
@TestPropertySource(locations="classpath:test.properties")
public @interface DefaultTestAnnotations { }

21

Một cách tiếp cận khác phù hợp để ghi đè một vài thuộc tính trong thử nghiệm của bạn, nếu bạn đang sử dụng @SpringBootTestchú thích:

@SpringBootTest(properties = {"propA=valueA", "propB=valueB"})

1
không SpringBootTesttải tập tin application.properies?
TuGordoBello

8

TLDR:

Vì vậy, những gì tôi đã làm là có tiêu chuẩn src/main/resources/application.propertiesvà cũng là src/test/resources/application-default.propertiesnơi tôi ghi đè một số cài đặt cho TẤT CẢ các thử nghiệm của mình.

Toàn bộ câu chuyện

Tôi đã gặp vấn đề tương tự và cho đến nay không sử dụng hồ sơ. Nó có vẻ khó chịu khi phải làm điều đó ngay bây giờ và nhớ khai báo hồ sơ - có thể dễ dàng bị lãng quên.

Bí quyết là, để tận dụng một cấu hình cụ thể application-<profile>.propertiesghi đè cài đặt trong cấu hình chung. Xem https://docs.spring.io/spring-boot/docs/civerse/reference/html/boot-features-external-config.html#boot-features-external-config-profile-specific-propericat .


3

Giải thích đơn giản:

Nếu bạn đang như tôi và bạn có cùng application.propertiestrong src/main/resourcessrc/test/resources, và bạn đang tự hỏi tại sao application.propertiestrong thư mục thử nghiệm của bạn không được trọng các application.propertiestài nguyên chính của bạn, hãy đọc tiếp ...

Nếu bạn có application.propertiesdưới src/main/resourcesvà cùng application.propertiesdưới src/test/resources, mà application.propertiesđược nhặt, phụ thuộc vào cách bạn đang chạy thử nghiệm của bạn . Cấu trúc thư mục src/main/resourcessrc/test/resources, là một quy ước kiến ​​trúc Maven, vì vậy nếu bạn chạy thử nghiệm của bạn như mvnw testhoặc thậm chí gradlew test, thì application.propertiestrong đó src/test/resourcessẽ được chọn, vì đường dẫn thử nghiệm sẽ đi trước đường dẫn lớp chính . Nhưng, nếu bạn chạy thử nghiệm như Run as JUnit Testtrong Elipse / STS, thì application.propertiestrongsrc/main/resources sẽ được chọn, vì đường dẫn chính trước kiểm tra đường dẫn .

Bạn có thể kiểm tra nó bằng cách mở Run > Run Configurations > JUnit > *your_run_configuration* > Click on "Show Command Line" .

Bạn sẽ thấy một cái gì đó như:

XXXbin \ javaw.exe -ea -Dfile.encoding = UTF-8-classpath XXX \ workspace-spring-tool-suite-4-4.5.1.RELEASE \ project_name \ bin \ main; XXX \ workspace-spring-tool-suite-4-4.5.1.RELEASE \ project_name \ bin \ test;

Bạn có thấy rằng \ main xuất hiện trước, sau đó \ test không? Phải, tất cả là về classpath :-)

Chúc mừng


1
I just configured min as the following :

spring.h2.console.enabled=true
spring.h2.console.path=/h2-console


# changing the name of my data base for testing
spring.datasource.url= jdbc:h2:mem:mockedDB
spring.datasource.username=sa
spring.datasource.password=sa



# in testing i don`t need to know the port

#Feature that determines what happens when no accessors are found for a type
#(and there are no annotations to indicate it is meant to be serialized).
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false`enter code here`

1

Nếu bạn đang sử dụng Spring 5.2.5 và Spring Boot 2.2.6 và muốn ghi đè chỉ một vài thuộc tính thay vì toàn bộ tệp. Bạn có thể sử dụng chú thích mới: @DAVEPropertySource

@SpringBootTest
@Testcontainers
class ExampleIntegrationTests {

    @Container
    static Neo4jContainer<?> neo4j = new Neo4jContainer<>();

    @DynamicPropertySource
    static void neo4jProperties(DynamicPropertyRegistry registry) {
        registry.add("spring.data.neo4j.uri", neo4j::getBoltUrl);
    }
}

0

Mặt khác, chúng tôi có thể thay đổi tên cấu hình thuộc tính mặc định, đặt thuộc tính spring.config.name=testvà sau đó có tài nguyên đường dẫn lớp, phiên src/test/test.propertiesbản gốc của chúng tôi org.springframework.boot.SpringApplicationsẽ được cấu hình tự động từ test.properations riêng biệt này, bỏ qua các thuộc tính ứng dụng;

Lợi ích: tự động cấu hình các bài kiểm tra;

Nhược điểm: phơi bày thuộc tính "spring.config.name" ở lớp CI

ref: http://docs.spring.io/spring-boot/docs/civerse/reference/html/common-application-properIES.html

spring.config.name = application # Tên tệp cấu hình


5
Bỏ qua application.propertieskhông phải là một tùy chọn cho tôi vì tôi chỉ muốn ghi đè một số giá trị cấu hình ban đầu trong thử nghiệm.
FrVaBe

Tôi đã tìm kiếm một cách để có một thử nghiệm duy nhất không tải src / main / resource / application.properations và đây là nó. Tạo một tệp: src / test / resource / blank.properies và thêm chú thích vào (các) thử nghiệm nên bỏ qua các thuộc tính chính. @TestPropertySource (property = "spring.config.name = trống")
rvertigo

Làm cách nào để đặt giá trị thuộc tính cụ thể cho từng phương pháp kiểm tra Junit?
Nicolas

0

Bạn cũng có thể tạo tệp application.properations trong src / test / resource nơi JUnits của bạn được viết.


Điều này giúp gì? ^^
jump_monkey
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.