Testing a controller with an auto wired component is null when calling the controller from a test case

后端 未结 3 1353
陌清茗
陌清茗 2021-01-16 05:05

I have a controller

@RestController
public class Create {

    @Autowired
    private ComponentThatDoesSomething something;

    @RequestMapping(\"/greeting\         


        
相关标签:
3条回答
  • 2021-01-16 05:31

    The @Autowired class can be easily mocked and tested with MockitoJUnitRunner with the correct annotations.

    With this you can do whatever you need to do with the mock object for the unit test.

    Here is a quick example that will test the Create method call with mocked data from ComponentThatDoesSomething.

    @RunWith(MockitoJUnitRunner.class)
    public class CreateTest {
    
        @InjectMocks
        Create create;
        @Mock
        ComponentThatDoesSomething componentThatDoesSomething;
    
        @Test
        public void testCallWithCounterOf4() {
    
            when(componentThatDoesSomething.getCounter()).thenReturn(4);
            String result = create.call();
            assertEquals("Hello World 4", result);
        }
    }
    
    0 讨论(0)
  • 2021-01-16 05:45

    Spring doesn't auto wire your component cause you instantiate your Controller with new not with Spring, so Component is not instatntiated

    The SpringMockMvc test check it correct:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    public class CreateTest {
        @Autowired
        private WebApplicationContext context;
    
        private MockMvc mvc;
    
        @Before
        public void setup() {
            mvc = MockMvcBuilders
                    .webAppContextSetup(context)
                    .build();
        }
    
        @Test
        public void testCall() throws Exception {
            //increment first time
            this.mvc.perform(get("/greeting"))
                    .andExpect(status().isOk());
            //increment secont time and get response to check
            String contentAsString = this.mvc.perform(get("/greeting"))
                    .andExpect(status().isOk()).andReturn()
                    .getResponse().getContentAsString();
            assertEquals("Hello World 2", contentAsString);
        }
    }
    
    0 讨论(0)
  • 2021-01-16 05:47

    Use Mockito and inject a mock that you create. I would prefer constructor injection:

    @RestController
    public class Create {
    
        private ComponentThatDoesSomething something;
    
        @Autowired
        public Create(ComponentThatDoesSomething c) {
            this.something = c;
        }
    }
    

    Don't use Spring in your Junit tests.

    public CreateTest {
    
        private Create create;
    
        @Before
        public void setUp() {
            ComponentThatDoesSomething c = Mockito.mock(ComponentThatDoesSomething .class);
            this.create = new Create(c);
        } 
    }
    
    0 讨论(0)
提交回复
热议问题