例外“必须存在至少一个JPA元模型".抛出控制器测试 [英] Exception "At least one JPA metamodel must be present" thrown in Controller-Test

查看:83
本文介绍了例外“必须存在至少一个JPA元模型".抛出控制器测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试测试用@RestController注释的控制器类.我正在使用Spring-Boot 1.5.10 .

I am trying to test a controller class annotated with @RestController. I am using Spring-Boot 1.5.10.

应用程序本身正常启动,但是单元测试失败.请记住,我目前正在尝试测试控制器(并嘲笑该服务-我将在以后测试服务).

The application itself starts up properly, but the unit test fails. Please bear in mind, that I am currently just trying to test the controller (and mock away the service - I will be testing the services later).

这是我的一些课程:

Application.java

package com.particles.authservice;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;

@SpringBootApplication
@Import({ ApplicationConfiguration.class })
public class Application {
    public static void main(final String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

ApplicationConfiguration.java

package com.particles.authservice;

import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.data.jpa.convert.threeten.Jsr310JpaConverters;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

@EntityScan(basePackageClasses = { Application.class, Jsr310JpaConverters.class })
@EnableJpaRepositories
public class ApplicationConfiguration {
}

AccountController.java

package com.particles.authservice.accountservice;

import ...

@RestController
public class AccountController {
    @Autowired
    private AccountService accountService;

    /**
     * This method attempts to login a user and issue a token if the login was successful.
     * <p>
     * If login fails due a login attempt with a non-existent username or an invalid password, an exception is thrown.
     * 
     * @param credentials
     *            ({@link Credentials}) credentials in a JSON-form, that can be unserialized into an object of this type
     * @param response
     *            ({@link HttpServletResponse}) response, which will be sent to the client;
     *            if the credentials were valid the response receives a JWT as an additional header
     * @return ({@link PersistableAccount}) JSON (automatically serialized from the given TO);
     *         if the request was successful, an additional header containing the freshly issued JWT is added into the response
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
    public PersistableAccount login(@RequestBody final Credentials credentials, final HttpServletResponse response)
            throws IOException, URISyntaxException {
        final Optional<PersistableAccount> account = accountService.login(credentials);
        if (!account.isPresent()) {
            throw new AccountLoginFailedException(credentials);
        }
        response.setHeader("Token", jwtService.tokenForPersistableAccount(account.get()));
        return account.get();
    }
}

AccountControllerTest.java

package com.particles.authservice;

import static ...
import ...

@RunWith(SpringRunner.class)
@WebAppConfiguration
@WebMvcTest(AccountController.class)
public class AccountControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private AccountService accountServiceMock;

    @Test
    public void test() throws Exception {
        final Credentials credentials = TestHelper.createCredentials();
        final Optional<PersistableAccount> account = Optional.of(TestHelper.createPersistableAccount());

        given(accountServiceMock.login(credentials))
                                                    .willReturn(account);

        mockMvc
               .perform(MockMvcRequestBuilders.post("/login").accept(MediaType.APPLICATION_JSON))
               .andExpect(status().isOk());
    }
}

为了简便起见,我已将 AccountController 简化为一个端点,并省略了导入.

I have reduced the AccountController to just one endpoint and omitted imports for brevity purposes.

该测试可以正常编译,但是每当我运行该测试时,都会收到以下(嵌套的)异常(缩短了-请告知您是否需要完整的堆栈跟踪信息):

The test compiles just fine, but whenever I run the test, I receive the following (nested) exception (shortened - let me know if you need the full stacktrace):

Caused by: java.lang.IllegalArgumentException: At least one JPA metamodel must be present!
    at org.springframework.util.Assert.notEmpty(Assert.java:277)
    at org.springframework.data.jpa.mapping.JpaMetamodelMappingContext.<init>(JpaMetamodelMappingContext.java:52)
    at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.createInstance(JpaMetamodelMappingContextFactoryBean.java:71)
    at org.springframework.data.jpa.repository.config.JpaMetamodelMappingContextFactoryBean.createInstance(JpaMetamodelMappingContextFactoryBean.java:26)
    at org.springframework.beans.factory.config.AbstractFactoryBean.afterPropertiesSet(AbstractFactoryBean.java:134)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1687)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1624)
    ... 40 more

我已经检查了很多类似的问题,但是解决此问题的常用方法似乎不适用于我的情况.我特别尝试了以下方法:

I have checked out a lot of similar questions, but the usual ways to resolve this did not seem to work in my case. In particular I tried the following:

  • Using spring-boot-starter-data-jpa (did not apply to me since I was using that dependency to begin with), managed version
  • Separating application from its (JPA-related) configuration due to problems in regards to @EnableJpaRepositories and possibly @EntityScan - to no avail (following the first reply in Getting "At least one JPA metamodel must be present" with @WebMvcTest, but while my application still starts just fine, the test still fails)
  • I have tried using JacksonTester - in fact I just want to test the controller functionality at the moment - to no avail either (ended up needing the context)
  • As far as I understand I am mocking away the actual service; so in fact I am not using any JPA Metamodels, am I?

删除@EnableJpaRepositories注释可以解决此问题,但不幸的是,这似乎破坏了我的应用程序.

Removing the @EnableJpaRepositories annotation solves the issue, but unfortunately it seems to break my application.

我在做什么错了?

推荐答案

添加ContextConfiguration.该测试没有看到ApplicationConfiguration,因此没有看到任何实体.

Add ContextConfiguration. The test did not see ApplicationConfiguration, hence did not see any entity.

@ContextConfiguration(classes = {ApplicationConfiguration.class})
public class AccountControllerTest { ... }

更新:

代码缺少的另一件事是@SpringBootTest.尝试用这个注释测试类.

Another thing the code is missing is @SpringBootTest. Try annotating the test class with this one.

这篇关于例外“必须存在至少一个JPA元模型".抛出控制器测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆