You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 12:57:12