NullPointerException от смоделированного bean-компонента в конструкторе. Как правильно смоделировать mockBean-компонент из конструктора, предварительно настроив его? - PullRequest
0 голосов
/ 11 января 2019

Я использую аннотацию @MockBean в своем тестовом классе для экземпляра WebClient.Builder, и это приводит к исключению NullPointerException при попытке установить контекст SSL.

Я не уверен, почему я не увидел ошибку, когда я не пытался установить контекст и просто вызывал api build (), как в v1, показанном ниже:

Класс обслуживания v1:

@Service
public class ABCD {

private static final Logger logger = LoggerFactory.getLogger(ABCD.class);

private String apiUrl;

private final WebClient webClient;
private final XYZRepository repository;

public ABCD(WebClient.Builder webClientBuilder,
                   XYZRepository repository, @Value("${api-root-url}") String apiUrl) {

    //------------------------
    this.webClient = webClientBuilder.build();
    //------------------------
    this.repository = repository;
    this.apiUrl = apiUrl;
    }
}

Класс обслуживания v2:

@Service
public class ABCD {

private static final Logger logger = LoggerFactory.getLogger(ABCD.class);

private String apiUrl;

private final WebClient webClient;
private final XYZRepository repository;

public ABCD(WebClient.Builder webClientBuilder,
                   XYZRepository repository, @Value("${api-root-url}") String apiUrl) throws SSLException {

    SslContext sslContext = SslContextBuilder
            .forClient()
            .trustManager(InsecureTrustManagerFactory.INSTANCE)
            .build();
    ClientHttpConnector httpConnector = new ReactorClientHttpConnector(options -> options.sslContext(sslContext));

    //------------------------
    this.webClient = webClientBuilder
            .clientConnector(httpConnector)
            .build();
    //------------------------
    this.repository = repository;
    this.apiUrl = apiUrl;
    }
}

Тестовый класс:

@RunWith(SpringRunner.class)
@WebFluxTest(ABCD.class)
public class ABCDTest {

    @MockBean
    XYZRepository repository;

    @MockBean
    WebClient.Builder webClientBuilder;

    @SpyBean
    ABCD ABCDService;


    WebClient webClient;

    @Value("${api-root-url}")
    String apiRootUrl;

    @Before
     public void setup() {
         this.objMapper = new ObjectMapper();
         this.mockWebServer = new MockWebServer();
         String baseUrl = this.mockWebServer.url("/").toString();
         this.webClient = WebClient.create(baseUrl);

         MockitoAnnotations.initMocks(this);
         ReflectionTestUtils.setField(ABCDService,
                 "apiRootUrl", API_ROOT_URL);
         ReflectionTestUtils.setField(ABCDService,
                 "webClient", this.webClient);
     }

    }

Здесь, в v2

this.webClient = webClientBuilder .clientConnector (httpConnector) .build ();

вызывает NPE при вызове build () . Как я могу издеваться над веб-клиентом, не вызывая NPE?

Я попытался добавить следующий код в метод setup () для проверки ответа метода clientConnector:

when(this.webClientBuilder.clientConnector(any()))
                .thenReturn(this.webClientBuilder);

Итак, мне любопытно, где этот код может быть добавлен для использования вышеупомянутой насмешки.

1 Ответ

0 голосов
/ 11 января 2019

Я полагаю, что webClientBuilder был создан нормально как макет (он не нулевой - да?), Но вы не сказали, что делать, когда к нему вызывается метод clientConnector. Поэтому по умолчанию Mockito возвращает ноль - отсюда ваш NPE, когда вы вызываете build() для этого ответа.

Таким образом, вам понадобится webClientBuilder для возврата из метода clientConnector и для возврата webClient из build(). Сделайте это, добавив следующие строки:

when(webClientBuilder.clientConnector(any(ClientHttpConnector.class))).thenReturn(webClientBuilder);
when(webClientBuilder.build()).thenReturn(webClient);
...