1

I'm trying to mock rest api call but facing an error while testing the controller class using WebMvcTest,

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.abc.center.entities.repositories.SomeRepository' 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:1486)
    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)
    ... 41 more

I have an project structure something like this,

enter image description here

I tried many ways but no luck, Below is my restcontroller and its Mockito test class and repository,

@Slf4j
@Component
@RequestMapping()
@Setter
public class SomeController {

    // Variable initialization

    @Autowired
    private  SometRepository someRepository;

        public void sendData(RecordNo rocordNo, String xmlString, SomeFile file) throws  ValidationException{
        ClientHttpRequestFactory requestFactory = new
                HttpComponentsClientHttpRequestFactory(HttpClients.createDefault());
        RestTemplate restTemplate = new RestTemplate(requestFactory);

        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
        messageConverters.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));

        restTemplate.setMessageConverters(messageConverters);

        MultiValueMap<String,String> header = new LinkedMultiValueMap<>();
        header.add("x-api-key",api_key);
        header.add("Content-Type",content_type);
        header.add("Cache-Control",cache_control);
        HttpEntity<String> request = new HttpEntity<>(xmlString, header);

        try {
            restTemplate.postForEntity(getUri(rocordNo,file), request, String.class);
        }catch (RestClientResponseException e){
            throw new ValidationException(e.getResponseBodyAsString());
        }

    }

    getUri(RecordNo rocordNo SomeFile file){
        // here I need someRepository which is an interface
    }

}


public interface TestRepository extends PagingAndSortingRepository<RecordNo, Integer> {
    //queries to repositories
}


@RunWith(SpringJUnit4ClassRunner.class)
@WebMvcTest(SomeController.class)
public class SomeControllerTestClass {

private TestController serviceToTest;

    private  String xmlString = "String";


    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext wac;

    @Mock
    private TestRepository testRepository;

    @Before
    public  void init(){
        serviceToTest.setTestRepository(testRepository);
        this.mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
        MockitoAnnotations.initMocks(this);
    }

    @Test
    public void verifySafe2Call() throws  Exception{
        mockMvc.perform(MockMvcRequestBuilders.post("someuri")
                .contentType(MediaType.APPLICATION_XML)
        .accept(MediaType.APPLICATION_JSON)
        .content(xmlString)).andExpect(jsonPath("$.responseMessage").value("Validation succeeded"))
        .andExpect(jsonPath("$.responseCode").value("SUCCESS"))
                .andDo(print());

}

Does my project structure is making any problem? I know it is not able to find the definition but not getting why it is so. Any suggestion would be nice.

tyro
  • 765
  • 2
  • 13
  • 34

3 Answers3

0

Try this, add following code to the controller:

@Autowired private SometRepository someRepository; public void setRepository(SomeRepository repository) { this.repository = repository;}

Rauf Aghayev
  • 300
  • 1
  • 12
  • @Setter annotation can serve the purpose of setting and tries that way as well but no its not working – tyro Sep 13 '17 at 14:15
  • Sorry, I miss that. Actually, I wouldn't use @Mock rather I'd use Autowired for repository and create bean for it in config class. – Rauf Aghayev Sep 13 '17 at 14:19
0

I don't see @EnableJpaRepositories annotation. Your config should be annotated with this annotation and Spring will scan the needed packages for repositories.

@Configuration
@EnableJpaRepositories(basePackages = {"com.abc.center.entities.repositories"})
public class JpaConfig {
}
Mykola Yashchenko
  • 5,103
  • 3
  • 39
  • 48
  • NoSuchBeanDefinitionException: No bean named 'entityManagerFactory' available And also Cannot create inner bean for someRepository again – tyro Sep 13 '17 at 14:24
  • By default, the EntityManagerFactory does not come for free. You should define it in your config. Like this https://stackoverflow.com/a/28603097/5207023 – Mykola Yashchenko Sep 13 '17 at 14:28
  • But I don't understand why do we need datasource to test controller class, I have not done this any where in the project where trying to mock the same repository. and also application.properties have everything in it. Any suggestion would be helpful I read the spring document for datasource but didnt gave my answer – tyro Sep 14 '17 at 08:50
  • because you have `@Autowired` your repository into controller class. Repository needs datasource. – Mykola Yashchenko Sep 14 '17 at 09:02
  • Ok, you can try `@SpringBootTest` annotation instead of `@WebMvcTest` – Mykola Yashchenko Sep 14 '17 at 09:24
0

I had a similar problem writing a unit/integration test with @WebMvcTest and I solved it by adding @ComponentScan("com.abc.center.entities.repositories") to SomeController (in your case).

croc
  • 1,416
  • 1
  • 18
  • 24