How to avoid using an interceptor in Spring boot integration tests

Viewed 2393

I have an issue while testing REST requests. On my application I have an interceptor that checks for token validity before allowing the requests. However for my integration tests I would like to bypass the check. In other words I'd like either to shunt the interceptor or to mock it to always return true.

Here is my simplified code:

@Component
public class RequestInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
            throws Exception {
        String token = request.getHeader("Authorization");
        if (token != null) {
            return true;
        } else {
            return false;
        }
    }
}


@Configuration
public class RequestInterceptorAppConfig implements WebMvcConfigurer {
    @Autowired
    RequestInterceptor requestInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
       registry.addInterceptor(requestInterceptor).addPathPatterns("/**");
    }

}

and the tests:

@SpringBootTest(classes = AppjhipsterApp.class)
@AutoConfigureMockMvc
@WithMockUser
public class DocumentResourceIT {

    @Autowired
    private DocumentRepository documentRepository;

    @Autowired
    private MockMvc restDocumentMockMvc;

    private Document document;

    public static Document createEntity() {
        Document document = new Document()
            .nom(DEFAULT_NOM)
            .emplacement(DEFAULT_EMPLACEMENT)
            .typeDocument(DEFAULT_TYPE_DOCUMENT);
        return document;
    }

    @BeforeEach
    public void initTest() {
        document = createEntity();
    }

    @Test
    @Transactional
    public void createDocument() throws Exception {
        int databaseSizeBeforeCreate = documentRepository.findAll().size();
        // Create the Document
        restDocumentMockMvc.perform(post("/api/documents")
            .contentType(MediaType.APPLICATION_JSON)
            .content(TestUtil.convertObjectToJsonBytes(document)))
            .andExpect(status().isCreated());
    }
}

When running the tests it always go through the interceptor and gets rejected since I have no valid token. My code here is simplified, I can not get a valid token for testing and so I really need to skip the interceptor.

Thanks for your help

2 Answers

To mock it (in an integration test):

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.when;

// non-static imports

@SpringBootTest
// other stuff
class IntegrationTest {
  @MockBean
  RequestInterceptor interceptor;

  // other stuff

  @BeforeEach
  void initTest() {
    when(interceptor.preHandle(any(), any(), any())).thenReturn(true);
    // other stuff
  }

  // tests
}

What @BeforeEach and @SpringBootTest do, you know; Mockito's any() just says "regardless of argument"; for @MockBean and Mockito's when-then, the Javadoc is good enough that I feel no need to add information.

I would solve this by using a profile on the interceptor. In your test you dont run with the profile (bean is not injected). In your production or which ever env you need it you run with the new profile.

of course you need to change the usage a bit. This should work:

@Configuration
public class RequestInterceptorAppConfig implements WebMvcConfigurer {
    @Autowired
    Collection<RequestInterceptor> requestInterceptors;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        requestInterceptors.forEach(interceptor -> registry.addInterceptor(interceptor).addPathPatterns("/**");
    }

}
Related