【问题标题】:How to unit test a Spring Boot MongoRepository?如何对 Spring Boot MongoRepository 进行单元测试?
【发布时间】:2015-11-05 09:15:27
【问题描述】:

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

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

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

我尝试过使用Embedded MongoDB,但我不知道如何从文件中插入测试数据。 我也尝试过使用NoSQLUnit,但是SpringApplicationConfiguration和单元测试配置冲突,导致读写不同的数据库。

【问题讨论】:

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


【解决方案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】:

    只需使用 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>
    

    【讨论】:

      【解决方案3】:

      这就是我所做的。

      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

      【讨论】:

        【解决方案4】:

        我遇到了同样的问题,我们使用了一个单独的 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)
        

        希望对您有所帮助。

        【讨论】:

          【解决方案5】:

          首先,确保您已将以下 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 父级,我们可以添加所需的依赖项而无需指定它们的版本:

          <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。下面的 sn-p 展示了如何手动配置嵌入式 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 也是如此。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-10-21
            • 2017-06-19
            • 1970-01-01
            • 1970-01-01
            • 2016-12-07
            相关资源
            最近更新 更多