如何在 spring 云合同的生产者控制器中模拟服务

how to mock the service in controller on producer for spring cloud contract

我一直在尝试在生产者端模拟控制器内部的服务

@Autowired
private Service service;

    @PostMapping(path = "/getone", consumes = "application/json", produces = "application/json")
public ResponseEntity<Response> getone(@RequestBody Test[] test) {
    String appId = Utils.getId();
    return new ResponseEntity<>(service.pub(test,id), HttpStatus.OK);
}

这是我的基础测试 class 的样子

@ExtendWith(SpringExtension.class)
@ActiveProfiles("test")
@SpringBootTest
@RunWith(PowerMockRunner.class)
public class ContractTest {
    
    @Autowired
    private WebApplicationContext context;

    @Mock
    private Service service;

    @BeforeEach
    void setup() {
        mockStatic(Utils.class);
        when(Utils.getId()).thenReturn("194");
       Mockito.when(service.pub(Mockito.any(Test[].class),eq("194"))).thenReturn(TestUtils.publish_success_response());
StandaloneMockMvcBuilder standaloneMockMvcBuilder = MockMvcBuilders.standaloneSetup(publishApiController, this.publishService);
RestAssuredMockMvc.standaloneSetup(standaloneMockMvcBuilder);
    }
  1. 实际服务 class 在这里运行,而不是导致问题的模拟?
    2.How 我们是否在 @Before 方法中测试失败场景?

有一个重要的区别between @Mock and @MockBean。对于您的测试,您需要 @MockBean,因为您要用 Spring 测试上下文的模拟替换 Spring bean。

除此之外,您正在混合使用 JUnit 4 (@RunWith) 和 JUnit 5 (@ExtendWith, @BeforeEach)。

如果您只想使用 MockMvc 为控制器编写测试,则不必使用 @SpringBootTest 启动整个 Spring 上下文。 Spring 启动测试只为您的 MVC 组件 start a sliced context 提供注解:@WebMvcTest.

对于 Utils class 的静态模拟,您可以使用 Mockito (since version 3.4.0) 来减少额外依赖项的数量并坚持 Spring 启动启动测试提供。

可能的测试如下所示:

// @ExtendWith(SpringExtension.class) not needed with recent Spring Boot versions
@ActiveProfiles("test")
@WebMvcTest
public class ContractTest {
    
    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private Service service;

    @Test
    void test() {
      
     try(MockedStatic<Utils> mockedUtils = Mockito.mockStatic(Utils.class)) {
        mockedUtils.when(Utils::getId).thenReturn("194");

        when(service.pub(Mockito.any(Test[].class),eq("194"))).thenReturn(TestUtils.publish_success_response());
        // ... your test
     }
      
    }
}