3
@RunWith(SpringRunner.class)
@WebAppConfiguration
Class Test{

@Autowired
public SomeBean someBean;

@Test
public void testAccountPage2() throws Exception {
 SomeBean someBean = mock(SomeBean.class);  
 given(someBean.getAccount(anyString())).willReturn(getCustomer());
}

Here someBean.getAccount(anyString()) is not mocking, which is calling the actual method of that bean impl. It seems it's taking the Autowired object not the mocked one.

Could anyone help me to mock beans in method level? those beans are also autowired in the same class or superclass.

Thanks

Mehraj Malik
  • 14,872
  • 15
  • 58
  • 85
Sankar C
  • 41
  • 1
  • 3
  • That will simply not work. You can mock them only at the class level for Spring Boot to take them into account. – M. Deinum Feb 19 '18 at 12:25
  • Then inside a method if we try to mock like this ? SomeBean someBean = mock(SomeBean.class); will it work or not ? – Sankar C Feb 19 '18 at 13:19
  • What isn't clear about *that will simply not work*. Yes you get a mock no Spring Boot doesn't know anything about it and internally it will still use the normal dependency. That will only work with `@MockBean`. – M. Deinum Feb 19 '18 at 13:20

2 Answers2

0

To replace a bean in the Spring container by a Mockito mock, use @MockBean.

import org.springframework.boot.test.mock.mockito.MockBean; // import to add

@RunWith(SpringRunner.class)
@WebAppConfiguration
Class Test{

  @MockBean
  public SomeBean someBean;

  @Test
  public void testAccountPage2() throws Exception {      
    given(someBean.getAccount(anyString())).willReturn(getCustomer());
  }
}

To understand the difference between Mockito and MockBean from Spring Boot, you can refer to this question.

davidxxx
  • 125,838
  • 23
  • 214
  • 215
  • Actually I can able to mock the bean using mockbean annotation but I want to use both autowired & mockbean in same class. eg autowired can be used in class level and mock object can be used in method level. is it possible in spring junit test? – Sankar C Feb 19 '18 at 13:24
  • No it is not possible out of the box. To achieve such a thing you should retrieve the dependency where you want inject a mock and set manually the mock. It makes much boiler plate code and it is not consistent as all other dependencies will not be updated. Maybe you should refine your question by explaining your requirement and not the solution. – davidxxx Feb 19 '18 at 13:40
  • Thanks davidxxx, I want to test my controller in which I want to call real service methods for part of the test cases and mock method methods for remaining test cases. Please suggest me how to achieve this ? – Sankar C Feb 19 '18 at 14:23
  • You are welcome :) I think that the cleaner way is defining two test classes : a unit test class where you mock some dependencies and an integration test class where you don't mock. – davidxxx Feb 19 '18 at 14:38
0

You need to inject the mock in order to have it working instead of autowiring

//if you are just testing bean/services normally you do not need the whole application context
@RunWith(MockitoJUnitRunner.class)
public class UnitTestExample {

    @InjectMocks
    private SomeBean someBean = new SomeBean();

    @Test
    public void sampleTest() throws Exception {
        //GIVEN

        given(
            someBean.getAccount(
            //you should add the proper expected parameter
                any()
            )).willReturn(
            //you should add the proper answer, let's assume it is an Account class
            new Customer()
        );

        //DO
        //TODO invoke the service/method that use the getAccount of SomeBean
        Account result = someBean.getAccount("");

        //VERIFY
        assertThat(result).isNotNull();
        //...add your meaningful checks
    }
}
Paizo
  • 3,986
  • 30
  • 45