3

I would have a question concerning Spring Data - MongoDB and JUnit test.

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { UserRepository.class, User.class })
public class MyJUnitTest {

The UserRepository looks like this:

@Repository
public interface UserRepository extends MongoRepository<User, String> {
    User findByUsername(final String username);
}

I get the following Exception:

Failed to instantiate [... .repository.UserRepository]: Specified class is an interface

My question now would be, how to do it, that UserRepository is instantiate although there is no implementation class because Spring Data does the implementation by its own? If I do not mark USerRepository with @Repository than Spring does not create a bean object

[EDIT]

I have tried the example of the link you posted and it works fine if I run the application over the main- method. Then I tried to implement a test class but in this case I get the same exception:

Error creating bean with name 'hello.test.TestClass': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private hello.CustomerRepository hello.test.TestClass.repository; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [hello.CustomerRepository] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}

My test class looks like this in src/test/java/hello/test (hello.test is the package):

@ComponentScan("hello")
@EnableMongoRepositories(basePackages = "hello")
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = { CustomerRepository.class,     Customer.class })
public class TestClass {

@Autowired
private CustomerRepository repository;

@Test
public void testMethod() {
    System.out.println("repositoryd: " + repository);
    }
}

and my CustomerRepository looks like this (with @Configuration annotation):

@Configuration
public interface CustomerRepository extends MongoRepository<Customer, String> {

public Customer findByFirstName(String firstName);

public List<Customer> findByLastName(String lastName);

}

Actually I don't know which annotations I need in order to get the test running - Maybe you would have another suggestion in order that I can solve this issue.

2
  • Remove the @Repository annotation from the UserRepository interface. Spring Data uses a different mechanism for discovering Spring Data Repository types Commented Jul 23, 2017 at 23:18
  • The link to the blog entry is dead... Commented Nov 30, 2018 at 12:25

4 Answers 4

3

For Spring Boot 1.5.8.RELEASE

You can use @SpringBootTest to bootstrap all you spring configurations.

Your test will look like

@RunWith(SpringRunner.class)
@SpringBootTest
public class SomeRepositoryTests {

    @Autowired
    private SomeRepository someRepository;

    @Test
    public void someTest() {
        someRepository.someMethod(...);
        // assertions
    }
}

Of course you want to use embedded mongodb for test so add

for Maven

<dependency>
  <groupId>de.flapdoodle.embed</groupId>
  <artifactId>de.flapdoodle.embed.mongo</artifactId>
  <scope>test</scope>
</dependency>

for Gradle

testCompile('de.flapdoodle.embed:de.flapdoodle.embed.mongo')
Sign up to request clarification or add additional context in comments.

4 Comments

Really so simple??? But what about @Autowired of services and other fields? Is @SpringBootTest able to autowire them? (I am using mockito for tests in Spring...)
What other fields?
I was thinking about several services and repositories.
Repositories should not depend on services and for other repositories you can just add like SomeRepository and if spring can find it it will load it.
1

Your repo CustomerRepository doesn't require @Configuration or @Repository annotations. Spring will do it for you as you extends base Repository classes.

To setup Mongo Repositories you need to extend ApplicationContext with the following annotations.

@Configuration
@EnableAutoConfiguration // create MongoTemplate and MongoOperations
@EnableMongoRepositories(basePackages = "hello.test") // Create your repos
public class ApplicationConfig {

}

You also would like to use in-memory database for you unit/integration tests so them won't alter productions database.

To enable it just add the following dependency:

<dependency>
  <groupId>de.flapdoodle.embed</groupId>
  <artifactId>de.flapdoodle.embed.mongo</artifactId>
  <version>1.50.2</version>
  <scope>runtime</scope>
</dependency>

Finally, configure you test class with the ApplicationContext

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = ApplicationConfig.class)
public class MyJUnitTest {
    // Test cases ...
}    

Comments

0

Within @SpringApplicationConfiguration you need to point to a configuration class. Neither UserRepository nor User probably are one I assume.

To get started with both Spring and Spring Data MongoDB fundamentals, be sure to check out this getting started guide.

1 Comment

Hello Oliver, I have tried the example of the link and it works fine - but I don't know how to run my test (I have edit my post above). It would be great if you can help me once agin - thanks a lot!
0

If using junit 5 and you want to start up spring in the most lightweight way possible you will need the following annotations on your IntegrationTest class

@DataMongoTest
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = {MyMongoService.class})
@EnableMongoRepositories(basePackageClasses = MyRepository.class)
public class MyMongoIntegrationTest {
    
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private MyRepository myRepository;

    @Autowired
    private MyMongoService myMongoService; <-- Assuming this injects MyRepository
    
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.