Весенняя загрузка @MockBean странное поведение - PullRequest
0 голосов
/ 29 ноября 2018

Этот вопрос относится к этому .Определив проблему и успешно применив предложенное решение, я продолжил разработку и рефакторинг своего кода, пока не достиг этой точки.

Как вы можете видеть в следующем коде, я определил bean-компонент для класса обслуживания, который был создан в моем контроллере GetExchangeRate, поэтому я внедряю его непосредственно в контроллер и избегаю внедрения его зависимостей (ExchangeRateView репозиторий, реализация которого использует JdbcTemplate).Затем я реорганизовал свой тест, поэтому мне не нужно высмеивать ExchangeRateView, а GetExchangeRate вместо этого.Однако после этого я получаю ошибку Application failed to start, жалуясь на то, что

Параметр 0 конструктора в com.fx.exchangerate.store.infrastructure.persistence.read.ExchangeRateJdbcView требует bean-компонентанаберите 'org.springframework.jdbc.core.JdbcTemplate'

Мне кажется, что, хотя я издеваюсь от аннотации GetExchangeRate до @MockBean, она все еще пытается получить свои зависимости отконтекст приложения, так как он работает правильно всякий раз, когда я добавляю @MockBean ExchangeRateView exchangeRateView в тестовый класс.

Итак, мой вопрос, действительно ли @MockBean ведет себя так?Нужно ли вводить зависимому классу свои зависимости?Я что-то здесь упускаю?

КОНТРОЛЛЕР:

@RestController
public class ExchangeRateStoreController {
    private AddExchangeRateRequestAdapter addExchangeRateRequestAdapter;
    private GetExchangeRate getExchangeRate;
    private CommandBus commandBus;

    @Autowired
    public ExchangeRateStoreController(CommandBus commandBus, GetExchangeRate getExchangeRate) {
        addExchangeRateRequestAdapter = new AddExchangeRateRequestAdapter();
        this.commandBus = commandBus;
        this.getExchangeRate = getExchangeRate;
    }

    @GetMapping
    public ExchangeRate get(@RequestBody GetExchangeRateRequest getExchangeRateRequest) {
        GetExchangeRateQuery query = new GetExchangeRateQuery(getExchangeRateRequest.from, getExchangeRateRequest.to, getExchangeRateRequest.date);
        return getExchangeRate.execute(query);
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public void create(@RequestBody AddExchangeRateRequest addExchangeRateRequest) {
        commandBus.dispatch(addExchangeRateRequestAdapter.toCommand(addExchangeRateRequest));
    }
}

ТЕСТ:

@RunWith(SpringRunner.class)
@WebMvcTest(ExchangeRateStoreController.class)
public class ExchangeRateStoreControllerTest {

    @Autowired
    private MockMvc mvc;
    @MockBean
    ExchangeRateRepository exchangeRateRepository;
    @MockBean
    ExchangeRateDateValidator exchangeRateDateValidator;
    @MockBean
    GetExchangeRate getExchangeRate;

    @Test
    public void givenValidAddExchangeRateRequest_whenExecuted_thenItReturnsAnHttpCreatedResponse() throws Exception {
        String validRequestBody = "{\"from\":\"EUR\",\"to\":\"USD\",\"amount\":1.2345,\"date\":\"2018-11-19\"}";

        doNothing().when(exchangeRateDateValidator).validate(any());
        doNothing().when(exchangeRateRepository).save(any());

        mvc.perform(post("/").content(validRequestBody).contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isCreated());
    }

    @Test
    public void givenGetExchangeRateRequestThatMatchesResults_whenExecuted_thenItReturnsOkResponseWithFoundExchangeRate() throws Exception {
        when(getExchangeRate.execute(any(GetExchangeRateQuery.class))).thenReturn(anExchangeRate());
        mvc.perform(get("/")
                .content("{\"from\":\"EUR\",\"to\":\"USD\",\"date\":\"2018-11-19\"}")
                .contentType(MediaType.APPLICATION_JSON))
                .andExpect(status().isOk());
    }
}

СЛУЖБА ПРИЛОЖЕНИЯ:

public class GetExchangeRate {

    private ExchangeRateView view;
    private Clock clock;

    public GetExchangeRate(ExchangeRateView view, Clock clock) {
        this.view = view;
        this.clock = clock;
    }

    // More methods here
}

КЛАСС РЕАЛИЗАЦИИ РЕАЛИЗАЦИИ:

@Repository
public class ExchangeRateJdbcView implements ExchangeRateView {

    JdbcTemplate jdbcTemplate;

    @Autowired
    public ExchangeRateJdbcView(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    // More methods here
}

КЛАСС КОНФИГУРАЦИИ:

@Configuration
public class ExchangeRateStoreConfig {

    @Bean
    @Autowired
    public GetExchangeRate getExchangeRate(ExchangeRateView exchangeRateView, Clock clock) {
        return new GetExchangeRate(exchangeRateView, clock);
    }

    @Bean
    public Clock clock() {
        return new Clock();
    }

    // More bean definitions
}

1 Ответ

0 голосов
/ 18 февраля 2019

Мне наконец удалось найти причину этой проблемы.Я выяснил, что это связано с тем, что в основной класс моей весенней загрузки был добавлен @ComponentScan(basePackages = {"com.mycompany.myapp.infrastructure", "com.mycompany.myapp.application"} ), поэтому @WebMvcTest не работал должным образом.

Вы можете найти объяснение в документации весенней загрузки:

Если вы используете тестовую аннотацию для тестирования более конкретного фрагмента вашего приложения, вам следует избегать добавления настроек конфигурации, которые являются специфическимив определенную область класса приложения основного метода.

Конфигурация сканирования базового компонента @SpringBootApplication определяет фильтры исключения, которые используются для обеспечения правильной работы среза.Если вы используете явную директиву @ComponentScan в своем классе, аннотированном @ SpringBootApplication, имейте в виду, что эти фильтры будут отключены.Если вы используете нарезку, вы должны определить их снова.

https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...