0

I am mocking AuthService in the test below and setting authService.checkAuthority(any(UserAuthority.class))as "true". It is actually getting set but in the actual method(authService.checkAuthority(UserAuthority.COMMENT_ACCESS)) it is getting the value as false.

@RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(ApplicationRunner.class) @WebAppConfiguration @Transactional public class TagsTest extends BaseWebTest { @Autowired private TagService tagService; @Autowired private TagRepository repository; UserDetailsDto currentUser; @Autowired protected AuthService authService; @Autowired protected StringRedisTemplate stringRedisTemplate; @Autowired protected FilterChainProxy filterChainProxy; @Autowired protected WebApplicationContext context; protected static MockMvc mvc; @Before @Override public void setUp() { MockitoAnnotations.initMocks(this); mvc = MockMvcBuilders.webAppContextSetup(context) .dispatchOptions(true) .addFilters(filterChainProxy) .build(); authService = Mockito.mock(AuthService.class); Mockito.reset(authService); when(authService.getCurrentUser()).then(i->(getCurrentUser())); when(authService.checkAuthority(any(UserAuthority.class))). thenReturn(true); login(WORKFLOW_USER); } 

Any help is appreciated. Thanks in advance !

2
  • Can you please confirm that AuthService and checkAuthority are both public and non-final? That's a common source of mocking trouble. Commented Dec 6, 2017 at 20:56
  • 1
    Thanks Jeff for the reply. yes they are public and non-final Commented Dec 6, 2017 at 22:16

1 Answer 1

1

Your specific issue might be solved just by removing this assignment:

authService = Mockito.mock(AuthService.class); 

Your goal here is to use SpringJUnit4ClassRunner to create some of the dependencies in your graph, and use Mockito to mock other dependencies. However, as in this SO answer, anything marked with @Autowired in your test is created before the @Before method is run. This means that your call to replace authService above will only overwrite the field in your test; it won't adjust or change any of the other @Autowired fields, which have already been created, and which are already using the authService that you've bound in your Spring configuration.

Unit tests

If this is a unit test, and you're simply testing TagsService and TagsRepository, you might want to create those objects manually by calling their constructor with a combination of @Mock and @Autowired fields:

TagRepository repository = new TagRepository(/*mock*/ authService); TagService tagService = new TagService(/*mock*/ authService, /*real*/ repository); 

(Mockito provides a way to automate the creation of mocks using @InjectMocks, but because it fails silently if it can't detect an appropriate mock, you might want to avoid that and call a constructor instead. See this article for some good reasons and solutions.)

Note that the above is only when you are working directly with objects in unit tests, not when you're relying on Spring's autowiring to inject objects deeper into your graph.

Integration tests

The test you posted looks like a web or integration test, so it looks like you want to replace the instances of authService with your mock during their creation. Typically this means making a change to the configuration XML or your ApplicationRunner, in order to instruct Spring to use a Mockito mock instead of your real AuthService. Though there are lots of ways to do this, you might want to favor using a Mockito-centric FactoryBean as in this article.

But wait! You may be using an ApplicationRunner that is already customized for Mockito. The line authService = Mockito.mock(AuthService.class); looks very much out-of-place for three reasons:

  1. you are overwriting an @Autowired field, which rarely makes sense
  2. you call Mockito.mock manually despite the existence of MockitoAnnotations.initMocks(this), which is generally preferred
  3. you immediately reset the mock you create

This suggests to me that your @Autowired authService may already be a mock, and may already have stubbing, which is why you have a leftover reset. If so, then your problem isn't anything about Mockito, other than that you (or someone) have overwritten the field and stubbed your local copy instead of the one that Spring installs throughout your web test. That'd make it an easy fix: Delete your field reassignment and you may be good to go.

Sign up to request clarification or add additional context in comments.

2 Comments

I am using Mockito to test the model and controller (controller -> model -> dao), so mocking the Dao only. I used Mock annotation or Mockito.mock(MyDao.class). I then use MockMvc.perform to call the controller, however the Dao (declared in the controller, autowired) is still going to the real Dao not the Mocked Dao. I am not sure why. Any help would be greatly appreciated. Thanks.
@KayKay I think that's a more substantial question than the comments would be good for. Please ask a new question, include enough surrounding code that an answerer could reproduce, and add a link to this question so answerers know you've seen it and are looking for ways to apply it. Good luck!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.