JGleason
JGleason

Reputation: 3956

Why can't I instantiate CrudRepository in @SpringBootTest for library without SpringBootApplication?

I have a simple CRUD repo I am trying to use in an Integration (IT) Test...

@Repository
public interface ItemRepository extends CrudRepository<Item, String> { }

So I create a simple Test to inject it...

@SpringBootTest(classes = {ItemRepository.class})
@RunWith(SpringJUnit4ClassRunner.class)
public class ItemRepoIT {
    @Autowired
    ItemRepository repo;

    @Test
    public void initialTest() throws JsonProcessingException {
      // do something with repo
    }
}

But when I run the test I get...

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [some.pkg.ItemRepository]: Specified class is an interface at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:70) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1310) ... 41 more

So how would Inject this into a test?

Upvotes: 1

Views: 791

Answers (2)

Gurkan İlleez
Gurkan İlleez

Reputation: 1583

@ContextConfiguration(classes = Application.class)
@ExtendWith(SpringExtension.class)
public class TestA {

    @Autowired
    private Repository repository;
 
    @Test
    public void test() {}

}

Application is the configuration class that will invoke all context. In your case please replace Application.class to main class or configuration class It is JUnit5 also so you can replace ExtendWith to RunWith

Upvotes: 2

RUARO Thibault
RUARO Thibault

Reputation: 2850

I think that is because when using @SpringBootTest(classes=ItemRepository.class), you are looking to load a @Configuration class. Because you are loading an instant Repository (it is an interface extending a Repository provided by Spring Data), you need more classes to be loaded on the ApplicationContext.

You are running a SpringBoot project, that means you are supposed to have a class annotated with @SpringBootApplication. Why don't you try this:

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class ItemRepoIT {
    @Autowired
    ItemRepository repo;

    @Test
    public void initialTest() throws JsonProcessingException {
      // do something with repo
    }
}

The default behaviour of @SpringBootTest is to look for the @SpringBootConfiguration (or the @SpringBootApplication) class in your class path.

You could try Slice testing with Spring. Here is an example:

@DataJpaTest
@RunWith(SpringJUnit4ClassRunner.class)
public class ItemRepoIT {
    @Autowired
    ItemRepository repo;

    @Test
    public void initialTest() throws JsonProcessingException {
      // do something with repo
    }
}

Here is the documentation.

Finally, in your situation, you could add a @SpringBootApplication in your test folder to have a fake application loading the entire class path.

Upvotes: 0

Related Questions