Reputation: 1950
I have a Spring MVC application . I want to test this controller:
@RunWith(SpringRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations = {
"classpath:testDatabaseContext.xml"
})
public class TimeControllerTests {
@Autowired
private WebApplicationContext wac;
private MockMvc mockMvc;
@Mock
private AutorisationService autorisationService;
@Before
public void setup() {
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
@Test
public void should_OK() throws Exception {
doReturn(User.builder().build()).when(autorisationService).findById(any(Date.class),anyLong(), 1L);
mockMvc.perform(get("/time/2")
.contentType(APPLICATION_JSON))
.andExpect(status().isOk());
}
}
but when I run the test I have this error:
org.mockito.exceptions.misusing.NullInsteadOfMockException:
Argument passed to when() is null!
Example of correct stubbing:
doThrow(new RuntimeException()).when(mock).someMethod();
Also, if you use @Mock annotation don't miss openMocks()
Upvotes: 1
Views: 1769
Reputation: 103
I see several reasons why this does not work :
A - @Mock alone is not enough to initialize a mock. You need either :
However I don't think this will be enough, which brings me to :
B - Your controller looks managed by spring, whereas your mocked AutorisationService is not.
I am assuming there that your controller uses an AutorisationService supposedly injected by spring.
You have several options here :
@InjectMocks
private SomeController someController;
@Mock
private AutorisationService autorisationService;
@Before
public void setup() {
MockitoAnnotations.initMocks();
this.mockMvc = MockMvcBuilders.standaloneSetup(someController).build();
}
Note the standaloneSetup method : the idea here is that you are not using a spring context (annotations at the top can then be removed).
Kind of a hack, but I use it on regular basis.
You have to provide a custom spring context, with a bean of type AutorisationService, but provided by mockito.
// All all other beans necessary
// You can use whatever you need in your context : @ComponentScan("somepackage"), @Import(Config1.class, Config2.class), @ImportResource("context.xml"), @Bean methods ...
@Configuration
class SpringWithMockitoConfig {
@Bean
AutorisationService autorisationService() {
return Mockito.mock(AutorisationService.class);
}
}
You will then have two constraint on your tests :
With this solution you don't need the beans your real AutorisationService relies on (I assume Dao's, DataSource and such).
Basicly only the mvc part.
Upvotes: 2