2016-03-14 3 views
0

Я реализую сервис, используя службу Spring Boot и Spring Cloud Config для предоставления значений конфигурации. В моей службе у меня есть несколько значений конфигурации, которые необходимо обновить, когда значение изменяется в удаленном Git-репо, и я использовал @RefreshScope, чтобы включить эту функцию.@RefreshScope, похоже, игнорирует mockito's mocks

Проблема возникает, когда я пытаюсь ввести макет для RestTemplate в этой службе, он, кажется, игнорирует его и вместо этого использует экземпляр с автоподстановкой. Если я прокомментирую аннотацию, она, похоже, работает нормально.

Вот код для службы:

@Service 
@RefreshScope 
public class MyServiceImpl implements MyService { 

    private static final Logger LOG = Logger.getLogger(MyServiceImpl.class); 

    @Autowired 
    public RestTemplate restTemplate; 

    @Value("${opts.default}") 
    private String default; 

    @Value("${opts.address}") 
    private String address; 

    @Value("${opts.separator}") 
    private String separator; 

    ... 


    } 

Тест Исходный код:

@RunWith(SpringJUnit4ClassRunner.class) 
@SpringApplicationConfiguration(classes = Application.class) 
public class ServiceTest { 

    @Mock 
    private RestTemplate restTemplate; 

    @Autowired 
    @InjectMocks 
    private MyServiceImpl service; 

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

    public void testMethod() throws Exception { 
     when(restTemplate.postForObject(anyString(), any(), eq(ServiceResponse.class), anyMap())).thenReturn(getSuccessfulResponse()); 

     ServiceResponse response = service.doYourStuff(); 

     Assert.assertNotNull(response); 
     Assert.assertTrue(response.isSuccessful()); 
    } 

    ... 
    } 

ответ

1

При добавлении @RefreshScope боб становится прокси вместо фактической реализации сырой. В настоящее время RestTemplate установлен на прокси, а не на базовый экземпляр. (Если вы отлаживаете, вы увидите, что ваш MyServiceImpl на самом деле больше похож на экземпляр MyServiceImpl$SpringCgLib#353234).

Чтобы исправить это, вам необходимо вручную установить зависимость, используя ReflectionTestUtils и AopTestUtils. Последний должен получить фактический прокси.

Удалить @InjectMocks аннотацию и добавьте следующие строки в ваш метод setup после инициализации издевается:

Object actualTarget = AopTestUtils.getUltimateTargetObject(service); 
ReflectionTestUtils.setfield(actualTarget, "restTemplate", restTemplate); 

Для более ранних версий, в 4.2 следующее может сделать трюк

Object actualTarget = (service instanceof Advised) ? ((Advised) service).getTargetSource().getTarget() : service; 

Проблема заключается в том, что Mockito не обнаруживает прокси и просто устанавливает поле. ReflectionTestUtils не обнаруживает прокси-сервер или, следовательно, ручную разворачивание. Я на самом деле вступил в эту ловушку пару раз раньше, что привело меня к созданию SPR-14050 этим утром, чтобы оно было встроено в ReflectionTestUtils, чтобы немного облегчить боль.

+0

Спасибо! Я добавил себя в качестве наблюдателя к этому вопросу –

+0

Btw, AopTestUtils класс, который вы используете вместо AopUtils? –

+0

Да, это исправлено тип .. –

Смежные вопросы