Spring Boot测试中的MockBean注释导致NoUniqueBeanDefinitionException

时间:2016-09-10 23:56:22

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

我在使用@MockBean注释时遇到问题。文档说MockBean可以替换上下文中的bean,但是我在单元测试中得到NoUniqueBeanDefinitionException。我看不出如何使用注释。如果我可以模拟repo,那么很明显会有多个bean定义。

我按照此处的示例进行操作:https://spring.io/blog/2016/04/15/testing-improvements-in-spring-boot-1-4

我有一个mongo存储库:

public interface MyMongoRepository extends MongoRepository<MyDTO, String>
{
   MyDTO findById(String id);
}

泽西岛资源:

@Component
@Path("/createMatch")
public class Create
{
    @Context
    UriInfo uriInfo;

    @Autowired
    private MyMongoRepository repository;

    @POST
    @Produces(MediaType.APPLICATION_JSON)
    public Response createMatch(@Context HttpServletResponse response)
    {
        MyDTO match = new MyDTO();
        match = repository.save(match);
        URI matchUri = uriInfo.getBaseUriBuilder().path(String.format("/%s/details", match.getId())).build();

        return Response.created(matchUri)
                .entity(new MyResponseEntity(Response.Status.CREATED, match, "Match created: " + matchUri))
                .build();
    }
}

JUnit测试:

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

    @Autowired
    private TestRestTemplate restTemplate;

    @MockBean
    private MyMongoRepository mockRepo;

    @Before
    public void setup()
    {
        MockitoAnnotations.initMocks(this);

        given(this.mockRepo.findById("1234")).willReturn(
                new MyDTO());
    }

    @Test
    public void test()
    {
        this.restTemplate.getForEntity("/1234/details", MyResponseEntity.class);

    }

}

错误讯息:

Field repository in path.to.my.resources.Create required a single bean, but 2 were found:
    - myMongoRepository: defined in null
    - path.to.my.MyMongoRepository#0: defined by method 'createMock' in null

3 个答案:

答案 0 :(得分:11)

这是一个错误:https://github.com/spring-projects/spring-boot/issues/6541

此修复位于spring-data 1.0.2-SNAPSHOT2.0.3-SNAPSHOThttps://github.com/arangodb/spring-data/issues/14#issuecomment-374141173

如果您不使用这些版本,可以通过声明模拟名称来解决此问题:

@MockBean(name="myMongoRepository")
private MyMongoRepository repository;

回复您的评论

来自Spring's doc

  

为方便起见,需要对已启动的REST调用的测试   服务器还可以@Autowire一个TestRestTemplate   解析正在运行的服务器的相对链接。

阅读本文,我认为您需要在网络环境中声明@SpringBootTest

@SpringBootTest(webEnvironment=WebEnvironment.RANDOM_PORT)

如果您的春季启动无法启动Web环境,那么TestRestTemplate需要什么。因此,我猜春天甚至没有它可用。

答案 1 :(得分:1)

我在 spring-boot 2.3.9 中遇到了同样的“问题”,但这不是错误,而是 bean 的配置问题。

至少,有两种方法可以解决:

在@MockBean注解中设置name参数:

在测试中,将 name 添加到 MockBean

@MockBean(name="myRepository")
private MyRepository diffrentName;

并在生产代码库中使用 myRepository 作为文件名:

@Autowired
private MyRepository myRepository;

@MockBean 的名称必须与字段名称相同。

将 MockBean 命名为与代码中的依赖项相同的文件。

在测试中,使用 MockBean 的正确名称归档:

@MockBean
private MyRepository customRepository;

并在生产代码库中使用 customRepository 作为文件名:

@Autowired
private MyRepository customRepository;

通过这种方式,您指明要使用哪个 bean。

我希望这对某人有帮助。

答案 2 :(得分:0)

只需在POM.xml中添加以下内容

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>