TestRestTemplate の Autowired にて NoSuchBeanDefinitionException が発生する

# 現象

下記のようなクラス構成のテストを書いたところ、TestRestTemplate が Autowired できない現象が発生しました。

```application.properties
# AP　は 9000 番ポートで動作させる
server.port=9000
```

```AbstractBaseTest.java
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = HogeApplication.class)
public abstract class AbstractBaseTest {

    protected MockMvc mvc;

    @Autowired
    protected WebApplicationContext context;

    @Autowired
    protected TestRestTemplate restTemplate;
```

```SubTestClass.java
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = HogeApplication.class)
public class SubTestClass extends AbstractBaseTest {
     something tests...
    public void URLをテストする() throws Exception {
        HashMap param = new HashMap<String, String>();
        param.put("userAccount", ユーザーアカウント);
        param.put("password", パスワード);
        ResponseEntity<String> resultResponse = restTemplate.postForEntity("http://localhost:9000/authentication", param, String.class);
     
    }
}
```

**ログの内容**
<pre>
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.boot.test.web.client.TestRestTemplate' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1493)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1104)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1066)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:585)
	... 28 more
</pre>

# 回避策
**サブクラスにて webEnvironment に RANDOMPORT、親クラスなどで@LocalServerPortを指定する**です。
[Spring Boot のページ](https://spring.io/guides/gs/testing-web/) のサンプルでは、LocalServerPort の指定があり、テストをするにあたり事実上不可欠のアノテーションですが、TestRestTemplate の生成については不要のようです。ドキュメントにも必須かどうかについての言及がありません。


>Note the use of webEnvironment=RANDOM_PORT to start the server with a random port (useful to avoid conflicts in test environments), and the injection of the port with @LocalServerPort. Also note that Spring Boot has provided a TestRestTemplate for you automatically, and all you have to do is @Autowired it.

２０１７/08 現在の動作としては、

+ 使用するクラスにて TestRestTemplate を Autowired しないと Bean を生成できない。
+ LocalServerPort のポートへ TestRestTemplate から要求しないと、Connection Refused になる。

のようです。
よって正しい構成は下記のようになるようです。

```AbstractTest.java
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) //あってもなくても良い
@ContextConfiguration(classes = HogeApplication.class)
public abstract class AbstractBaseTest {

    protected MockMvc mvc;

    @Autowired
    protected WebApplicationContext context;

    @Autowired
    protected TestRestTemplate restTemplate;

    @LocalServerPort
    protected int serverPort;
}
```

```SubTestClass.java
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@ContextConfiguration(classes = HogeApplication.class)
public class SubTestClass extends AbstractBaseTest {
     something tests...
    public void URLをテストする() throws Exception {
        HashMap param = new HashMap<String, String>();
        param.put("userAccount", ユーザーアカウント);
        param.put("password", パスワード);
        ResponseEntity<String> resultResponse = restTemplate.postForEntity("http://localhost:" + serverPort + "/authentication", param, String.class);
     
    }
}
```

@LocalServerPort が存在しない場合、該当のアプリケーションにモックの HTTP 経由でアクセスできないようです。
ConnectionRefused のエラーが発生します。

<pre>
org.springframework.web.client.ResourceAccessException: I/O error on POST request for "http://localhost:9000/hoge": Connection refused (Connection refused); nested exception is java.net.ConnectException: Connection refused (Connection refused)

	at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:666)
	at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:613)
	at org.springframework.web.client.RestTemplate.postForEntity(RestTemplate.java:407)
	at org.springframework.boot.test.web.client.TestRestTemplate.postForEntity(TestRestTemplate.java:471)
	at com.asaas.billing.controller.SigninControllerTest.URLをテストする(SigninControllerTest.java:72)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
	at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
	at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
	at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
	at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)

Caused by: java.net.ConnectException: Connection refused (Connection refused)
	at java.net.PlainSocketImpl.socketConnect(Native Method)
	at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:350)
	at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:206)
</pre>