如何对Spring Boot MongoRepository进行单元测试?

时间:2015-08-12 16:25:04

标签: mongodb spring-boot spring-data-mongodb

在我的Spring Boot Web应用程序中,我使用MongoDB来存储数据。在应用程序中,我使用扩展MongoRepository的接口访问数据库。

如何为此类存储库类设置单元测试?我想要的是

  • 启动MongoDB的嵌入式/内存实例
  • 从JSON或XML插入testdata
  • 使用自动装配的存储库对testdata执行查询

我尝试过使用Embedded MongoDB,但我无法弄清楚如何从文件中插入testdata。 我也尝试使用NoSQLUnit,但SpringApplicationConfiguration与单元测试配置冲突,导致不同的数据库进行读写。

5 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,我们使用了一个单独的MongoConfiguration类来为我们的测试指定一个特定的配置。

您可以使用EmbeddedMongoBuilder创建嵌入式mongo实例,如下所示:

import com.mongodb.Mongo;
import cz.jirutka.spring.embedmongo.EmbeddedMongoBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;
import java.net.ServerSocket;

@Configuration
public class MongoConfiguration {

    @Bean
    public Mongo mongo() throws IOException {
        System.setProperty("DB.TRACE","true");
        return new EmbeddedMongoBuilder()
            .version("2.13.1")
            .bindIp("127.0.0.1")
            .port(allocateRandomPort())
            .build();
    }
}

然后在您的测试类中,指定您要将该特定配置与@Import注释一起使用:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@Import(MongoConfiguration.class)

希望有所帮助。

答案 1 :(得分:1)

2018和Spring Boot 2的更新。首先,您可以根据documentation对嵌入式数据库进行仅数据集成测试。这使用DataMongoTest注释。这只配置了使mongoDB测试成为可能的必要依赖项。

如果要进行完整集成测试,请添加AutoConfigureDataMongo注释:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
@AutoConfigureDataMongo
public class PriceApiControllerIT {

pom.xml中应该具有的依赖关系:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.0.1.RELEASE</version>
</parent>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>de.flapdoodle.embed</groupId>
        <artifactId>de.flapdoodle.embed.mongo</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

答案 2 :(得分:0)

这就是我所做的。

public interface UserRepository extends MongoRepository<Users, Long> {

    public void deleteByUserId(String userId);

    public List<Users> findAllByUserStatus(String userStatus);
}

@Document
public class Users {

    @Id
    private long id;

    @Transient
    public static final String SEQUENCE_NAME = "users_sequence";

    @Indexed
    @NotNull
    private String userId;

    private String firstName;
    private String lastName;
    private String userType;
    private String userStatus;

    @Email
    private String emailId;

    @Size(min = 10, max = 10)
    @NumberFormat
    private String phoneNumber;

    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getUserId() {
        return userId;
    }

    public void setUserId(String userId) {
        this.userId = userId;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getUserType() {
        return userType;
    }

    public void setUserType(String userType) {
        this.userType = userType;
    }

    public String getEmailId() {
        return emailId;
    }

    public void setEmailId(String emailId) {
        this.emailId = emailId;
    }

    public String getPhoneNumber() {
        return phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public static String getSequenceName() {
        return SEQUENCE_NAME;
    }

    public String getUserStatus() {
        return userStatus;
    }

    public void setUserStatus(String userStatus) {
        this.userStatus = userStatus;
    }

}

这是junit

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MockodsApplication.class)
@SpringBootTest
@AutoConfigureMockMvc
public class UserControllerIT {

    @Autowired
    private UserRepository userRepository;

    @Autowired
    MongoTemplate mongoTemplate;

    @Autowired
    private MockMvc mvc;

    @After
    public void tearDown() {

    }

    @Test
    public void test1() {
        Users user = new Users();
        long userId = 1L;
        user.setId(userId);
        user.setFirstName("FirstName");
        user.setLastName("FirstName");
        user.setEmailId("fisrtname.secondname@gmail.com");
        user.setPhoneNumber("1234567890");

        assertEquals(user, userRepository.save(user));
    }

    @Test
    public void test2() {
        List<Users> persistedUser = userRepository.findAll();
        assertEquals("fisrtname.secondname@gmail.com", persistedUser.get(0).getEmailId());
    }
}

此链接帮助我实现了https://dzone.com/articles/spring-integration-tests

答案 3 :(得分:0)

首先,请确保已将以下Spring Boot父项添加到您的项目中:

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.2.2.RELEASE</version>
    <relativePath /> <!-- lookup parent from repository -->
</parent>

自从我们添加了Spring Boot parent之后,我们就可以添加所需的依赖项而无需指定其版本:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

spring-boot-starter-data-mongodb将启用Spring支持 MongoDB

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

de.flapdoodle.embed.mongo提供嵌入式MongoDB进行集成 测试

添加de.flapdoodle.embed.mongo依赖性后,Spring Boot将在运行测试时自动尝试下载并启动嵌入式MongoDB。以下代码段显示了如何手动配置嵌入式MongoDB实例

class EmbeddedMongoDbIntegrationTest {
    private MongodExecutable mongodExecutable;
    private MongoTemplate mongoTemplate;

    @After
    void clean() {
        mongodExecutable.stop();
    }

    @Before
    void setup() throws Exception {
        String ip = "localhost";
        int port = 27017;

        IMongodConfig mongodConfig = new MongodConfigBuilder().version(Version.Main.PRODUCTION)
            .net(new Net(ip, port, Network.localhostIsIPv6()))
            .build();

        MongodStarter starter = MongodStarter.getDefaultInstance();
        mongodExecutable = starter.prepare(mongodConfig);
        mongodExecutable.start();
        mongoTemplate = new MongoTemplate(new MongoClient(ip, port), "test");
    }

    @Test
    void test() throws Exception {
        // given
        DBObject objectToSave = BasicDBObjectBuilder.start()
            .add("key", "value")
            .get();

        // when
        mongoTemplate.save(objectToSave, "collection");

        // then
        assertThat(mongoTemplate.findAll(DBObject.class, "collection")).extracting("key")
            .containsOnly("value");
    }
}

注意,我们可以快速创建配置为使用的MongoTemplate bean 我们手动配置的嵌入式数据库,并将其注册到 Spring容器,因此您的mongo存储库将开始利用此容器 以及mongoTemplate。

答案 4 :(得分:0)

只需使用Spring Boot中的@DataMongoTest

@RunWith(SpringRunner.class)
@DataMongoTest
public class FooRepositoryTest {

    @Autowired
    FooRepository fooRepository;

    @Before
    public void setUp() throws Exception {
        fooRepository.save(new Foo());
    }

    @Test
    public void shouldBeNotEmpty() {
        assertThat(fooRepository.findAll()).isNotEmpty();
    }
}

依赖项

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
    <groupId>de.flapdoodle.embed</groupId>
    <artifactId>de.flapdoodle.embed.mongo</artifactId>
    <scope>test</scope>
</dependency>