如何在 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);
}
- 实际服务 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
}
}
}
我一直在尝试在生产者端模拟控制器内部的服务
@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);
}
- 实际服务 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
}
}
}