matthieusb
matthieusb

Reputation: 505

Mock rest endpoint without instantianting controller class

I am mostly a Spring Boot user when it comes to making rest apis, so I am not always comfortable with classic Spring projects using xml configuration.

However, I need to mock a rest endpoint for testing on that particular of project. There is also some DBUnit to mock the database values. Here is the code of the rest controller I am using :

@Path("/endpoint")
@Repository("myRestImpl")
public class MyRESTImpl implements MyREST {

    private static final Logger LOGGER = LogManager.getLogger(SalarieRESTImpl.class);

    @Context
    private MessageContext jaxrsContext;

    @Resource
    private WebServiceContext jaxwsContext;

    @Value(value = "${base.url}")
    private String baseUrl;

    @Autowired
    public SomeService someService;

    @Autowired
    private SomeOtherService someOtherService;

    @Override
    @GET
    @Path("/test")
    @Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
    public Response getSalarieInfoByMatricule() {
        LOGGER.info("Simple 404 test", matricule);
        ResponseBuilder response = null;

        esponse = Response.status(404);

        return response.build();
    }
}

And here is the (obviously not working) code of the test class I wrote :

@ContextConfiguration(locations = { "classpath:/tu-dao-beans.xml" })
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({ DependencyInjectionTestExecutionListener.class, DirtiesContextTestExecutionListener.class,
        DbUnitTestExecutionListener.class })
@DatabaseSetup(value = { "/db_data/dao/common.xml" })
@DbUnitConfiguration(dataSetLoader = ReplacementDataSetLoader.class)
public class MyMockMvcTest {

    @Autowired
    MyRESTImpl myRESTImpl;

    @Autowired
    private MappingJackson2HttpMessageConverter jacksonMessageConverter;

    private MockMvc mockMvc;

    @Before
    public void setup() {
        MockitoAnnotations.initMocks(this);

        this.mockMvc = MockMvcBuilders.standaloneSetup(myRESTImpl)
    .setMessageConverters(jacksonMessageConverter).build();
    }

    @Test
    public void test() throws Exception {
        mockMvc.perform(get("/endpoint/test")).andExpect(status().isNotFound());
    }
} 

When I run this, I get a Dispatcher servlet exception like the following :

java.lang.NoClassDefFoundError: org/springframework/web/servlet/DispatcherServlet
    at org.springframework.test.web.servlet.setup.MockMvcBuilders.standaloneSetup(MockMvcBuilders.java:75)
    at primobox.demat.webservices.rest.salarie.SalarieRESTImplIntMockMvcTest.setup(SalarieRESTImplIntMockMvcTest.java:36)
    at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
    at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
    at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
    at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
    at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
    at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
Caused by: java.lang.ClassNotFoundException: org.springframework.web.servlet.DispatcherServlet
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 10 more

I know that I am supposed to instantiate the myRESTImpl class. However it does not have a constructor (This is not my code). I think I have an understanding problem of how the dependencies work in that kind of spring app.

What is the workaround to properly use MockMvc in that case ?

Thanks for your help.

Upvotes: 0

Views: 890

Answers (1)

ootero
ootero

Reputation: 3475

Based on the annotations, seems that MyRESTImpl uses JAX-RS to implement the endpoint(s) (@Path, @Context, @GET) instead of Spring MVC. I wouldn't expect this.mockMvc = MockMvcBuilders.standaloneSetup(myRESTImpl); to work for non-Spring web endpoints, MockMvc doesn't start a servlet container.

I can see a few more errors:

java.lang.NoClassDefFoundError: org/springframework/web/servlet/DispatcherServlet. DispatcherServlet is not in the classpath, most-likely because spring-web artifact is not a dependency included in your pom.xml and a kind of confirmation the endpoints are not implemented using Spring Web.

private static final Logger LOGGER = LogManager.getLogger(SalarieRESTImpl.class); is using the wrong class.

An semantically this seems an endpoint implementation which is also a @Repository (or Dao implementation) where service dependencies are injected into. That seems weird, you would normally inject Dao into Services and Services into Controllers or Endpoint implementations.

Upvotes: 2

Related Questions