首页 文章

测试Spring引导REST资源问题

提问于
浏览
0

有一个使用Spring Boot制作的微服务 . 它由Jetty,Jersey,Jackson和Liquibase组成 . 此服务的任务之一是通过REST接收一些数据并返回响应 . 此操作将通过下一个单元:

  • MyResource@Component 带有JAX-RS注释的REST,它接收数据并询问 @Autowired MyService 以获得响应 .

  • MyService@Component 服务 @Autowired MyResource 要求其回复 .

  • MyResource ,简单的 @JpaRepository 界面

这个应用程序工作正常,但现在我需要为每个模块添加一些测试 . 通常我使用Mockito测试单位,所以我用模拟的MyRepository测试我的服务(Mockito @Mock annotation when()方法) . 我想以同样的方式测试MyResource.java .

我尝试使用TestRestTemplate方法测试spring-boot-starter-test,我的测试类如下所示:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebIntegrationTest(randomPort = true)
public class MyResourceTest {
  @Value("${local.server.port}")
  private int port;

  private String getBaseUrl() {
    return "http://localhost:" + port;
  }

  @Test
  public void test() {
    final TestRestTemplate restTemplate = new TestRestTemplate();
    assertEquals(restTemplate.postForEntity(getBaseUrl() + "/test", null, ResponseObject.class).getBody(), new ResponseObject());
  }
}

而且有两个问题 . 首先 - 当我的测试运行时,它们运行整个spring应用程序,所以我的liquibase脚本试图找到数据库,这是一个非常长的过程 . 第二 - 我无法用Mockito代理替换MyService类 .

我试图找到一些关于测试Spring启动REST应用程序的最佳实践的手册,我找到了基于MockMvc的方法,但它似乎没有运行服务器来运行测试 . 你能分享一下你在 Spring 季启动时测试REST资源的方法吗?

2 回答

  • 1

    MockMvc是您的问题的首选解决方案 . 它运行Spring启动应用程序,但“嘲笑”请求,因此它不会真正运行在http上,但表现如此 . 您可以使用@Autowired将应用程序的所有bean注入到测试类中,这样就可以在那里模拟spring bean .

  • 2

    我在6类配置/支持上运行所有测试 .

    AbstractTest 配置测试核心

    @ActiveProfiles(resolver = TestActiveProfilesResolver.class)
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    @IntegrationTest
    @SpringApplicationConfiguration(classes = Application.class)
    public abstract class AbstractTest {
       ...
    }
    

    AbstractRepositoryTest 通过jdbc jdbi测试我的存储库

    @Transactional
    public abstract class AbstractRepositoryTest<R> extends AbstractTest implements Repositories {
    
        @Inject
        private ObjectMapper mapper;
    
        @Inject
        protected Repositories repositories;
    
        private final Class<R> repositoryType;
    
        ...
    }
    

    AbstractServiceTest 来测试我的服务,这个类包含我服务测试的核心

    public abstract class AbstractServiceTest {
        ...
    }
    

    AbstractIntegrationTest 包含我的集成测试的核心,用于测试控制器的utils方法等 .

    public abstract class AbstractIntegrationTest extends AbstractTest {
        ...
    }
    

    ApplicationAbstractTest 提供了运行测试的上下文,这个classe与我用来运行spring boot应用程序的类相同

    @SpringBootApplication
    public class Application extends SpringBootServletInitializer {
        public static void main(final String[] args) {
            SpringApplication.run(Application.class, args);
        }
    
        @Override
        protected SpringApplicationBuilder configure(final SpringApplicationBuilder application) {
            return application.sources(Application.class);
        }
        ...
    }
    

    并且最终 TestActiveProfilesResolver ,提供匹配 application-test.properties 的配置文件,这是必要的,因为在JIRA上存在未解决的问题,here

    public class TestActiveProfilesResolver implements ActiveProfilesResolver {
    
        @Override
        public String[] resolve(final Class<?> testClass) {
            final String activeProfile = System.getProperty("spring.profiles.active");
            return new String[] {activeProfile == null ? "test" : activeProfile};
        }
    
    }
    

    有时我的测试扩展 AbstractRepositoryTestAbstractIntegrationTestsAbstractServiceTest ,这取决于我想要的 . 这个配置解决了测试服务,控制器等所有问题 .

相关问题