cybel
cybel

Reputation: 401

MockMvc tests always returns status code 200 for get requests

I I am very new to spring boot and only have been working with it for a couple of days, so I am also very confused about this project (which is not my own). I am supposed to write tests with MockMvc for the rest controller, however each test with MockMvc only returns the status code 200 although it should be a 404.
Here is one of the tests:

@WebMvcTest(ObjectController.class)
@SpringJUnitConfig(TestConfig.class)
        
public class MvcTest {
        
       @Autowired
      MockMvc mockMvc;
            
          @Test
          public void shouldReturn404() throws Exception {
                 
              mockMvc.perform(MockMvcRequestBuilders.get("/obj/123"))
                  .andExpect(MockMvcResultMatchers.status().is(HttpStatus.NOT_FOUND.value()));
          }
      }

This is my rest controller I would like to test.

@RestController
@RequestMapping("obj")
public class ObjectController {

    @Autowired
    MyClass myClass;

    @GetMapping()
    public List<MyObject> findAll() {
        List<MyObject> objList;
        objList = myClass.getObjects();
        return objList;
    }

    @GetMapping("/{id}")
    public MyObject findById(@PathVariable String id) {
        for (MyObject obj : myClass.getObjects()) {
            if (obj.getId().equals(id))
                return obj;
        }
        return null;
    }
}

Then there is this class:

public class MyClass {

    private List<MyObject> objList = new ArrayList<MyObject>();

    public MyObject addObject(MyObject obj) {
        objList.add(obj);
        return obj;
    }

    public void setObjects(List<MyObject> objList) {
        this.objList = objList;
    }

    public synchronized List<MyObject> getObjects() {
        return objList;
    }

}

There is an xml file that belongs to the class looking like this which can be found in the resource folder:

<?xml version='1.0' encoding='ISO-8859-1'?>
<beans xmlns='http://www.springframework.org/schema/beans'
    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xmlns:context='http://www.springframework.org/schema/context'
    xsi:schemaLocation='http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd'>

    <bean id='MyClass' class='it.is.some.path.MyClass'>
        <property name='objList'>
            <list>
                <ref bean='[R01] Object1' />
            </list>
        </property>
    </bean>
</beans>

The referenced beans can be found in separate files under resources too, in a sub folder called 'objList' and look like this:

<?xml version='1.0' encoding='ISO-8859-1'?>
<beans xmlns='http://www.springframework.org/schema/beans'
    xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
    xmlns:context='http://www.springframework.org/schema/context'
    xsi:schemaLocation='http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd'>

    <bean id='[R01] Object1' class='this.is.some.path.MyObject'>
        <property name='id' value='123' />
    </bean>
</beans>

The myclass.xml as well as the folder with all xmls of the objects are imported via @ImportResource in the Application class.

And then there is

public class MyObject {

    public String id = RandomStringUtils.randomAlphanumeric(5);

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }
}

am sorry for the lengthy explanation but I have been spending two days now trying to figure out how to get MockMvc running and I feel like I am completely stuck. I would be very, very grateful if anybody could help out.

Upvotes: 3

Views: 4689

Answers (1)

rieckpil
rieckpil

Reputation: 12051

I assume 200 is the correct response as you have a mapping for /obj/{id} where {id} is a placeholder for any path variable like 123 in /obj/123.

Even though your controller returns null from a code perspective, Spring won't map this automatically to a 404 not found if this is what you would expect.

So you can literally try it with every path variable, you'll always get HTTP 200 because there wasn't any exception and the DisptacherServlet could properly route the HTTP request to a controller mapping. HTTP 200 is the default response code if you don't specify anything.

If you want your controller endpoint to return 404 when your MyObject is null, you have to be more explicit about this, e.g.:

@GetMapping("/{id}")
public ResponseEntity<MyObject> findById(@PathVariable String id) {
    for (MyObject obj : myClass.getObjects()) {
        if (obj.getId().equals(id))
            return ResponseEntity.ok(obj);
    }
    return ResponseEntity.status(HttpStatus.NOT_FOUND).body(null);
}

Upvotes: 3

Related Questions