簡體   English   中英

春季啟動:在單元/集成測試期間,Bean為空

[英]Spring-boot: Beans are null during unit/integration test

我是sprint-boot的新手。 我有一個spring-boot應用程序,可以在常規路徑下正常工作。 現在,當我嘗試編寫單元/集成測試時,我發現我的bean為空。

感謝您在理解為什么它們為null以及如何解決它方面的任何幫助。 似乎根本無法從yml中獲取屬性。如果需要更多說明,請告訴我。

要澄清結構:

主班:

@SpringBootApplication
@EnableConfigurationProperties(ApplicationConfiguration.class)
public class Application {

  public static void main(String[] args) {
    ApplicationContext context = SpringApplication.run(Application.class, args);
  }
}

屬性文件(src / main / java / resources / application.yml)

http:
  url:
    protocol: http
    baseUrl: ${CONNECTOR_BASE_URL}
    connectorListUrl : connectors

使用上述屬性(ApplicationConfiguration.java)的配置類為:

@ConfigurationProperties(prefix = "http.url")
@Validated
@Data
public class ApplicationConfiguration {

  private String protocol;
  private String baseUrl;
  private String connectorListUrl;
}

現在,我要在上面編寫測試的類(ContinuousMonitorServiceTask.java)的簡化版本如下所示:

@Component
@Slf4j
public class ContinuousMonitorServiceTask extends TimerTask {

  @Autowired MonitorHttpClient httpClient;

  @Autowired ApplicationConfiguration config;



  @PostConstruct
  public void setUp() {
    connectorListUrl =
        config.getProtocol() + "://" + config.getBaseUrl() + "/" + config.getConnectorListUrl();

    connectorListHeaderParams.clear();
    connectorListHeaderParams.put("Accept", "application/json");
    connectorListHeaderParams.put("Content-Type", "application/json");

    connectorListGetRequest = new HttpGet(connectorListUrl);
    httpClient.setHeader(connectorListGetRequest, connectorListHeaderParams);
  }

  public void fetchList() {

    try {

      response = httpClient.callApi("Get Connector List", connectorListGetRequest);
      log.info(response.toString());

      connectorListResponseHandler(response);

    } catch (Exception e) {

      log.error(e.getMessage());
    }
  }
}

當我執行時,上面的代碼工作正常。

現在, 當我編寫test時 ,我需要模擬api調用 ,因此,我使用了MOCK-SERVER,並且我的testSimple1測試通過了,這是一個簡單的測試,可以查看模擬服務器是否可以啟動並返回預期的響應。 但是,在調試simpleTest2時 ,我看到了

  • monitorTask為空
  • appConfig為空
  • monitorTask為空

雖然,我有src / test / resources / application.yml為:

http:
    url:
        protocol: http
        baseUrl: 127.0.0.1:8080
        connectorListUrl : connectors

我的猜測是appConfig在測試過程中無法從application.yml中獲取屬性,因此一切都為空。但是,我不確定100%實時發生了什么。

這是我的測試類的樣子(有點臟代碼,但我將其置於當前狀態以顯示到目前為止我已經嘗試過的東西):

//@RunWith(MockitoJUnitRunner.class)
//@TestPropertySource(locations="classpath:application.yml")
//@RunWith(SpringJUnit4ClassRunner.class)
//@SpringApplicationConfiguration(ApplicationConfiguration.class)
@RunWith(SpringRunner.class)
@SpringBootTest(classes = ApplicationConfiguration.class)
//@EnableConfigurationProperties(ApplicationConfiguration.class)
public class ContinousMonitorTest {

  private MockMvc mockMvc;

  @Mock private MonitorHttpClient httpClient;

  @Mock private ApplicationConfiguration appConfig;

  @InjectMocks
  //@MockBean
  //@Autowired
  private ContinuousMonitorServiceTask monitorTask;

  TestRestTemplate restTemplate = new TestRestTemplate();
  HttpHeaders headers = new HttpHeaders();

  private static ClientAndServer mockServer;

  @BeforeClass
  public static void startServer() {
    mockServer = startClientAndServer(8080);
  }

  @AfterClass
  public static void stopServer() {
    mockServer.stop();
  }

  private void createExpectationForInvalidAuth() {
    new MockServerClient("127.0.0.1", 8080)
            .when(
                    request()
                            .withMethod("GET")
                            .withPath("/validate")
                            .withHeader("\"Content-type\", \"application/json\""),
                            //.withBody(exact("{username: 'foo', password: 'bar'}")),
                    exactly(1))
            .respond(
                    response()
                            .withStatusCode(401)
                            .withHeaders(
                                    new Header("Content-Type", "application/json; charset=utf-8"),
                                    new Header("Cache-Control", "public, max-age=86400"))
                            .withBody("{ message: 'incorrect username and password combination' }")
                            .withDelay(TimeUnit.SECONDS,1)
            );
  }


  private GenericResponse hitTheServerWithGETRequest() {
    String url = "http://127.0.0.1:8080/validate";
    HttpClient client = HttpClientBuilder.create().build();
    HttpGet post = new HttpGet(url);
    post.setHeader("Content-type", "application/json");
    GenericResponse response=null;

    try {
      StringEntity stringEntity = new StringEntity("{username: 'foo', password: 'bar'}");
      post.getRequestLine();
     // post.setEntity(stringEntity);
      response=client.execute(post, new GenericResponseHandler());

    } catch (Exception e) {
      throw new RuntimeException(e);
    }
    return response;
  }

  @Test
  public void testSimple1() throws Exception{

    createExpectationForInvalidAuth();

    GenericResponse response = hitTheServerWithGETRequest();
    System.out.println("response customed : " + response.getResponse());
    assertEquals(401, response.getStatusCd());


    monitorTask.fetchConnectorList();
  }

  @Test
  public void testSimple2() throws Exception{

    monitorTask.fetchConnectorList();
  }

如上面的@second所建議的,我對testSimple2測試進行了更改以使其看起來像並且解決了上述問題。

@Test
public void testSimple2() throws Exception{

  mockMvc = MockMvcBuilders.standaloneSetup(monitorTask).build();
  Mockito.when(appConfig.getProtocol()).thenReturn("http");
  Mockito.when(appConfig.getBaseUrl()).thenReturn("127.0.0.1:8080");
  Mockito.when(appConfig.getConnectorListUrl()).thenReturn("validate");
  Mockito.when(httpClient.callApi(Mockito.any(), Mockito.any())).thenCallRealMethod();

  monitorTask.setUp();
  monitorTask.fetchConnectorList();
}

或者,可以這樣做:

@Before
public void init()
{
  MockitoAnnotations.initMocks(this);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM