如何在Spring-boot中编写REST控制器端点的单元测试而不模拟Service类



我必须在Spring-boot中为Web服务编写单元测试,该单元测试应该从控制器执行测试,也可以流入服务类。我使用@Mock注释服务类和@InjectMock控制器,因此应用程序流永远不会进入服务类,(它返回一个null)。

如果Service类上没有@Mock注释,我将收到一个null点异常。

我不想模拟Service类,我想用同样的测试单元测试Service类。

这是我的REST控制器。

 @RestController
 public class AddressController {
 @Autowired
 private GetAddressService getAddressService;
@RequestMapping(value=ApplicationConstant.ADDRESS_URI,method=RequestMethod.G    ET,produces = { ApplicationConstant.APP_RESP_TYPE })
public @ResponseBody SampleResponse getAddress(
        @RequestParam(value="id",required=true) String hcId,
        @RequestParam(value="mbrNbrbr",required=true) String mbrNbr,
        ){
    System.out.println("Request ID in Controller :"+Id);
    String responseid = getAddressService.getAddress(Id);
    SampleResponse smapleResp = new SampleResponse();
    System.out.println("Response ID in Controller :"+Id);
    smapleResp.setResponseid(responseid);
    return smapleResp;

这是我的Service Class

 @Service
public class GetAddressServiceImpl implements GetAddressService {
@Override
public String getAddress(String id) {
    System.out.println("ID in Service : " + id);
    return id;
}
}

我有一个抽象测试类,它扩展到抽象控制器测试类,最后我的地址控制器测试类有@Test方法。

测试类:

 @RunWith(SpringJUnit4ClassRunner.class)
 @SpringApplicationConfiguration(classes = Application.class)
 public abstract class AbstractTest {
  }

抽象控制器测试类:

@WebAppConfiguration 
public abstract class AbstractControllerTest extends AbstractTest {
//mockmvc stimulates Http interactions
protected MockMvc mockMvc; 
@Autowired
protected WebApplicationContext webApplicationContext;

protected void setUp(){
    mockMvc =   MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

protected void setUp(AddressController addressController){
    mockMvc = MockMvcBuilders.standaloneSetup(addressController).build();
}
}

Finally My Address Test class:

   @TestExecutionListeners
    public class AddressMockControllerTest extends AbstractControllerTest  {
    @Mock
    private GetAddressService getAddressService;
    @InjectMocks
    private AddressController addressController;
    private String MockURI ="/v1/legacy/member/Contact/Address? id=55555&mbrNbr=20&id=ABC&productid=1FGQ&sourceid=STAR&addressuid=adasdsa";
    @Before
    public void setUp(){
        MockitoAnnotations.initMocks(this);
        setUp(addressController);       
        }

    @Test
    public void test(){
        System.out.println("In Unit test");
    }
    @Test
    public void testgetAddress() throws Exception {

     System.out.println("In Unit test");
     MvcResult result =  this.mockMvc.perform(
                   MockMvcRequestBuilders.get(MockURI)
                  .accept(MediaType.APPLICATION_JSON))
                  .andReturn(); 

     String content = result.getResponse().getContentAsString();
        System.out.println("In Unit test and content is " + content);   
    }

Boot Main Class:

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

应用程序初始化:

    @Configuration
@EnableAutoConfiguration
@ComponentScan(value={"com.ABC"})
@EnableConfigurationProperties
public class ApplicationInitializer {
    @Bean
    @ConditionalOnMissingBean(RequestContextListener.class)
    public RequestContextListener requestContextListener() {
        return new RequestContextListener();
    }
    @Bean
    public ServletRegistrationBean dispatcherRegistration(DispatcherServlet dispatcherServlet) {
        ServletRegistrationBean registration = new ServletRegistrationBean(
                dispatcherServlet);
        registration.addUrlMappings("/");
        return registration;
    }
    @Bean
    public ServletRegistrationBean dynamicLogbackLevelServletRegistration() {
        return new ServletRegistrationBean(new DynamicLogbackLevelServlet(),"/loglevel");
    }

    @Order(Ordered.HIGHEST_PRECEDENCE)
    public FilterRegistrationBean contextFilterRegistrationBean() {
        FilterRegistrationBean registrationBean = new FilterRegistrationBean();
        RequestFilter contextFilter = new RequestFilter();
        registrationBean.setFilter(contextFilter);
        registrationBean.setOrder(1);
        return registrationBean;
    }

    @Bean
    public ApplicationContextProvider applicationContextProvider(){
        return new ApplicationContextProvider();
    }
}

不确定这是否会起作用,但基于另一个SO帖子:https://stackoverflow.com/a/32294564/1499549

看起来你不应该使用standaloneSetup()如果你正在使用运行器

public void setup() {
    mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}

然后去掉@InjectMocks注释,用@Autowired代替。

//@Mock
//private GetAddressService getAddressService;
//@InjectMocks
@Autowired
private AddressController addressController;
private String MockURI ="/v1/legacy/member/Contact/Address?id=55555&mbrNbr=20&id=ABC&productid=1FGQ&sourceid=STAR&addressuid=adasdsa";
@Before
public void setUp(){
    setUp();       
}
@Test
public void test(){
    System.out.println("In Unit test");
}

顺便说一句,Spring Boot现在已经内置了对基于@MockedBean注释的mock和间谍bean的支持。

相关内容

  • 没有找到相关文章

最新更新