Spring Boot集成MongoDB测试报错:UnsatisfiedDependencyException求助
Spring Boot + MongoDB 测试报错排查:UnsatisfiedDependencyException
错误信息
org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'contactService' defined in file [/Users/gs97ahn/Development/spring-workspace/gabojait-spring/out/production/classes/com/inuappcenter/gabojaitspring/user/service/ContactService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contactRepository' defined in com.inuappcenter.gabojaitspring.user.repository.ContactRepository defined in @EnableMongoRepositories declared on MongodbConfiguration: Cannot resolve reference to bean 'mongoTemplate' while setting bean property 'mongoOperations'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mongoTemplate' defined in class path resource [com/inuappcenter/gabojaitspring/config/MongodbConfiguration.class]: Unsatisfied dependency expressed through method 'mongoTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoDbFactory' defined in class path resource [com/inuappcenter/gabojaitspring/config/MongodbConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.mongodb.MongoDatabaseFactory]: Factory method 'mongoDbFactory' threw exception; nested exception is java.lang.IllegalArgumentException: state should be: databaseName does not contain '/'
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'contactRepository' defined in com.inuappcenter.gabojaitspring.user.repository.ContactRepository defined in @EnableMongoRepositories declared on MongodbConfiguration: Cannot resolve reference to bean 'mongoTemplate' while setting bean property 'mongoOperations'; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'mongoTemplate' defined in class path resource [com/inuappcenter/gabojaitspring/config/MongodbConfiguration.class]: Unsatisfied dependency expressed through method 'mongoTemplate' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mongoDbFactory' defined in class path resource [com/inuappcenter/gabojaitspring/config/MongodbConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.data.mongodb.MongoDatabaseFactory]: Factory method 'mongoDbFactory' threw exception; nested exception is java.lang.IllegalArgumentException: state should be: databaseName does not contain '/'
提供的代码文件
测试代码
import com.inuappcenter.gabojaitspring.user.domain.Contact; import com.inuappcenter.gabojaitspring.user.dto.ContactDefaultResponseDto; import com.inuappcenter.gabojaitspring.user.dto.ContactSaveRequestDto; import com.inuappcenter.gabojaitspring.user.service.ContactService; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.data.mongodb.MongoTransactionException; import org.springframework.transaction.annotation.Transactional; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; @SpringBootTest public class ContactServiceIntegrationTest { @Autowired ContactService contactService; @Test @Transactional public void noDuplicateEmail() { // given ContactSaveRequestDto request = new ContactSaveRequestDto(); request.setEmail("email@domain.com"); // when ContactDefaultResponseDto response = contactService.saveTest(request); // then Contact foundContact = contactService.findByEmail(response.getEmail()); assertThat(response.getEmail()).isEqualTo(foundContact.getEmail()); } }
Contact 实体类
import lombok.Builder; import lombok.Getter; import lombok.NoArgsConstructor; import org.springframework.data.annotation.Id; import org.springframework.data.mongodb.core.index.Indexed; import org.springframework.data.mongodb.core.mapping.Document; import javax.validation.constraints.NotBlank; import java.time.LocalDateTime; @Getter @Document(collection = "contact") @NoArgsConstructor public class Contact { @Id private String id; @NotBlank @Indexed(unique = true) private String email; @NotBlank private String verificationCode; @NotBlank private Boolean isVerified; @NotBlank private Boolean isRegistered; @NotBlank private LocalDateTime createdDate; @NotBlank private LocalDateTime modifiedDate; @NotBlank private String schemaVersion; @Builder(builderClassName = "ByContactBuilder", builderMethodName = "ByContactBuilder") public Contact(String email) { this.email = email; } public void setVerificationCode(String verificationCode) { this.verificationCode = verificationCode; } public void setIsVerified(Boolean isVerified) { this.isVerified = isVerified; } public void setIsRegistered(Boolean isRegistered) { this.isRegistered = isRegistered; } public void setCreatedDate(LocalDateTime createdDate) { this.createdDate = createdDate; } public void setModifiedDate(LocalDateTime modifiedDate) { this.modifiedDate = modifiedDate; } public void setSchemaVersion(String schemaVersion) { this.schemaVersion = schemaVersion; } }
Repository 接口
import com.inuappcenter.gabojaitspring.user.domain.Contact; import org.springframework.data.mongodb.repository.MongoRepository; import java.util.Optional; public interface ContactRepository extends MongoRepository<Contact, String> { public Optional<Contact> findByEmail(String email); }
Service 类
import com.inuappcenter.gabojaitspring.user.domain.Contact; import com.inuappcenter.gabojaitspring.user.dto.ContactDefaultResponseDto; import com.inuappcenter.gabojaitspring.user.dto.ContactSaveRequestDto; import com.inuappcenter.gabojaitspring.user.repository.ContactRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.Optional; import java.util.Random; @Service @Slf4j @RequiredArgsConstructor @Transactional(readOnly = true) public class ContactService { private final ContactRepository contactRepository; @Transactional public ContactDefaultResponseDto saveTest(ContactSaveRequestDto request) { Contact savedContact = contactRepository.save(request.toEntity()); savedContact.setVerificationCode(generateVerificationCode()); return new ContactDefaultResponseDto(savedContact); } private String generateVerificationCode() { String chars = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; Random random = new Random(); random.setSeed(System.currentTimeMillis()); StringBuilder sb = new StringBuilder(6); for (int i = 0; i < 6; i++) sb.append(chars.charAt(random.nextInt(chars.length()))); return sb.toString(); } public Contact findByEmail(String email) { try { Optional<Contact> contact = contactRepository.findByEmail(email); if (contact.isEmpty()) { log.error(""); throw new IllegalStateException(); } else { return contact.get(); } } catch (Exception e) { log.error("", e); throw new IllegalStateException(); } } }
MongoDB 配置类
import com.mongodb.ConnectionString; import com.mongodb.MongoClientSettings; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.MongoDatabaseFactory; import org.springframework.data.mongodb.MongoTransactionManager; import org.springframework.data.mongodb.config.AbstractMongoClientConfiguration; import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; import java.util.Collection; import java.util.Collections; @Configuration @EnableMongoRepositories(basePackages = "com.inuappcenter.gabojaitspring") public class MongodbConfiguration extends AbstractMongoClientConfiguration { @Bean MongoTransactionManager transactionManager(MongoDatabaseFactory dbFactory) { return new MongoTransactionManager(dbFactory); } @Override protected String getDatabaseName() { return "gabojait"; } @Override public MongoClient mongoClient() { final ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/gabojait/?retryWrites=false"); final MongoClientSettings mongoClientSettings = MongoClientSettings.builder() .applyConnectionString(connectionString) .build(); return MongoClients.create(mongoClientSettings); } @Override public Collection<String> getMappingBasePackages() { return Collections.singleton("com.inuappcenter.gabojaitspring"); } }
application.properties 配置
spring.data.mongodb.authentication-database=admin spring.data.mongodb.username=root spring.data.mongodb.password=pass spring.data.mongodb.database=gabojait spring.data.mongodb.port=27017 spring.data.mongodb.host=localhost
问题根源及修复方案
1. 连接字符串格式错误(核心问题)
错误日志的关键提示是databaseName does not contain '/',问题出在MongodbConfiguration类的连接字符串:数据库名gabojait后面多了一个斜杠/,导致MongoDB解析数据库名时识别到无效字符。
修复方式:去掉连接字符串中的多余斜杠
final ConnectionString connectionString = new ConnectionString("mongodb://localhost:27017/gabojait?retryWrites=false");
2. 配置重复冲突
你同时在MongodbConfiguration硬编码了连接信息,又在application.properties中配置了MongoDB参数,会导致配置冲突。建议统一配置方式:
- 方式一:删除硬编码,改为读取配置文件参数
@Autowired private Environment env; @Override public MongoClient mongoClient() { String uri = String.format("mongodb://%s:%s@%s:%d/%s?authSource=%s&retryWrites=false", env.getProperty("spring.data.mongodb.username"), env.getProperty("spring.data.mongodb.password"), env.getProperty("spring.data.mongodb.host"), env.getProperty("spring.data.mongodb.port", Integer.class), env.getProperty("spring.data.mongodb.database"), env.getProperty("spring.data.mongodb.authentication-database")); final ConnectionString connectionString = new ConnectionString(uri); final MongoClientSettings mongoClientSettings = MongoClientSettings.builder() .applyConnectionString(connectionString) .build(); return MongoClients.create(mongoClientSettings); }
- 方式二:删除自定义
MongodbConfiguration,Spring Boot会自动根据application.properties创建Mongo相关Bean,仅保留事务管理器Bean(如果需要事务支持)。
3. 实体类验证注解错误
Contact实体类中,@NotBlank注解被错误用于Boolean和LocalDateTime类型字段,该注解仅适用于字符串类型,会导致验证失败。需替换为@NotNull:
// 修复前 @NotBlank private Boolean isVerified; @NotBlank private Boolean isRegistered; @NotBlank private LocalDateTime createdDate; @NotBlank private LocalDateTime modifiedDate; // 修复后 @NotNull private Boolean isVerified; @NotNull private Boolean isRegistered; @NotNull private LocalDateTime createdDate; @NotNull private LocalDateTime modifiedDate;
4. 其他优化点
- 测试方法中的
@Transactional会在测试结束后回滚数据,适合集成测试,但需确保MongoDB版本为4.0+(支持事务)。 ContactService的findByEmail方法可简化:
public Contact findByEmail(String email) { return contactRepository.findByEmail(email) .orElseThrow(() -> new IllegalStateException("未找到邮箱对应的Contact记录")); }
内容的提问来源于stack exchange,提问作者gs97ahn
相关产品推荐
相关产品推荐

