当前位置: 首页 > 知识库问答 >
问题:

用Spock进行控制器测试中的模拟Spring服务

商松
2023-03-14

我正在寻找一种方法来模拟Controller中使用的服务bean,这样我就可以使用MockMVC只测试Controller。但是我找不到一个简单的方法来用Spock Mock代替real bean。一切都使用spring-boot 1.3.2版本。更多细节如下:

我有一个以下控制器类

@RestController
@RequestMapping(path = "/issues")
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class NewsletterIssueController {

  private final GetLatestNewsletterIssueService latestNewsletterIssueService;

  @RequestMapping(
    method = RequestMethod.GET,
    path = "/latest"
  )
  public ResponseEntity getLatestIssue() {
    Optional<NewsletterIssueDto> latestIssue = latestNewsletterIssueService.getLatestIssue();

    if (latestIssue.isPresent()) {
        return ResponseEntity.ok(latestIssue.get());
    } else {
        return ResponseEntity.notFound().build();
    }
  }
}

和集成Spock测试:

@ContextConfiguration(classes = [Application], loader = SpringApplicationContextLoader)
@WebAppConfiguration
@ActiveProfiles("test")
class NewsletterIssueControllerIntegrationSpec extends Specification {

  MockMvc mockMvc

  @Autowired
  GetLatestNewsletterIssueService getLatestNewsletterIssueService

  @Autowired
  WebApplicationContext webApplicationContext

  def setup() {
    ConfigurableMockMvcBuilder mockMvcBuilder = MockMvcBuilders.webAppContextSetup(webApplicationContext)
    mockMvc = mockMvcBuilder.build()
  }

  def "Should get 404 when latest issue does not exist"() {
    given:
        getLatestNewsletterIssueService.getLatestIssue() >> Optional.empty() // this won't work because it is real bean, not a Mock
    expect:
        mockMvc.perform(MockMvcRequestBuilders
                .get("/issues/latest")
                .contentType(JVM_BLOGGERS_V1)
                .accept(JVM_BLOGGERS_V1)
        ).andExpect(MockMvcResultMatchers.status().isNotFound())
  }

}

我需要一种方法来替换这个autowired bean,用一个mock/stub这样我就可以在“给定”部分定义交互。

共有1个答案

越学博
2023-03-14

我将在测试中创建一个本地配置,并在那里重写bean。

我不知道Groovy,但在Java中它会这样:

@ContextConfiguration(classes = NewsletterIssueControllerIntegrationSpec.Conf.class, loader = SpringApplicationContextLoader.class)
@WebAppConfiguration
@ActiveProfiles("test")
class NewsletterIssueControllerIntegrationSpec extends Specification {
  @Configuration
  @Import(Application.class)
  public static class Conf {
    @Bean
    public GetLatestNewsletterIssueService getLatestNewsletterIssueService() {
      return mock(GetLatestNewsletterIssueService.class);
    }
  }

  // […]
}

注意:这种方法可以很好地与Mockito一起工作,但是您可能需要Spock的预发布版本才能工作,请参见:https://github.com/spockframework/Spock/pull/546

顺便说一句:Spring Boot1.4将提供@mockbean构造来简化这一点。

 类似资料:
  • 问题内容: 我有一个ParseService,我想对其进行模拟以测试使用它的所有控制器,我一直在阅读有关茉莉花间谍的信息,但对我来说仍然不清楚。谁能给我一个关于如何模拟定制服务并在Controller测试中使用它的示例吗? 现在,我有一个使用服务插入书的控制器: 服务是这样的: 到目前为止,我的测试如下所示: 现在测试失败: 我做错了什么? 问题答案: 我做错的是没有在beforeEach中将模拟

  • > 解析某些文件的服务 管理文件系统的ServiceB 我想测试ControllerClass,特别是:

  • 我有一个Spring 3.2 MVC应用程序,正在使用Spring MVC测试框架测试控制器动作的GET和POST请求。我使用Mockito来模拟服务,但我发现模拟被忽略了,我的实际服务层被使用了(因此,数据库被击中)。 控制器测试中的代码: 你会注意到我有两个上下文配置文件;这是一种黑客行为,因为如果我无法阻止控制器测试命中实际的服务层,那么该服务层的存储库也可能指向测试数据库。我再也不能忍受这

  • 问题内容: 我有以下情况: controller.js controllerSpec.js 错误: 我也尝试过类似的方法,但没有成功: 我该如何解决?有什么建议? 问题答案: 有两种方法(或肯定有更多方法)。 想象一下这种服务(无论它是工厂都没关系): 使用此控制器: 一种方法是使用要使用的方法创建对象并对其进行监视: 然后,将其作为dep传递给控制器​​。无需注入服务。那可行。 另一种方法是模拟

  • 我试图在Spring boot 2中编写一个测试类,其中: 我想测试一个控制器 我想嘲笑一个仓库 我想按原样注入一个服务(即不嘲笑它) 该类看起来像: 的(唯一)实现是用注释的,并允许通过其构造函数注入仓库: 运行测试时,我得到了一个,大致上说是“没有可用”。 我怀疑我可能需要一个特定的测试配置来获得服务,但是我被可用的在线文献弄糊涂了。 有指针吗?

  • 我的目标是建立一个环境,让CircleCI在不同的浏览器中运行BrowserStack上的e2e测试。 我的测试假设有一个模拟服务器在运行。(例如,测试正在检查是否已对模拟服务器进行了某个调用。)