danielbchaves
danielbchaves

Reputation: 113

Mockito throws NotAMockException using spring mvc injection

Hy guys,

I am trying to make a test using mockito on a web application that uses spring mvc. When it executes this line "Mockito.reset(notificacaoRepositoryMock);" it throws "org.mockito.exceptions.misusing.NotAMockException: Argument should be a mock, but is: class com.sun.proxy.$Proxy40"

I saw that in am example and it worked, I can't find what I am doing wrong here.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestContext.class, WebAppConfig.class})
@WebAppConfiguration
public class NotificacaoControllerTest {

    private MockMvc mockMvc;

    @Autowired
    private NotificacaoRepository notificacaoRepositoryMock;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Before
    public void setUp() {
        // *** Error here ***
        Mockito.reset(notificacaoRepositoryMock);

        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

My TestContext is:

@Configuration
public class TestContext {

       @Bean
        public MessageSource messageSource() {
            ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();

            messageSource.setBasename("i18n/messages");
            messageSource.setUseCodeAsDefaultMessage(true);

            return messageSource;
        }

        @Bean
        public NotificacaoRepository notificacaoRepository() {
            return Mockito.mock(NotificacaoRepository.class);
        }
}

The class I want mock is a CrudRepository interface

public interface NotificacaoRepository extends CrudRepository<Notificacao, Long> {
}

and, I think, the relevant part of my pom.xml is (spring versions and mockito)

<properties>
    <hibernate.version>4.2.0.Final</hibernate.version>
    <mysql.connector.version>5.1.21</mysql.connector.version>
    <spring.version>4.1.6.RELEASE</spring.version>
    <spring.data.version>1.8.0.RELEASE</spring.data.version>
</properties>
...
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-aop</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-jpa</artifactId>
      <version>${spring.data.version}</version>
  </dependency>

<dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-core</artifactId>
    <version>1.9.5</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>3.2.3.RELEASE</version>
    <scope>test</scope>
</dependency>

UPDATE

@jfcorugedo i tryed exactly what you said but I keep receiving the same error. My test context is just

@Configuration
public class TestContext {
        @Bean
        @Primary
        public NotificacaoRepository notificacaoRepository() {
            return Mockito.mock(NotificacaoRepository.class);
        }
}

and my test class now is:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebAppConfig.class})
@WebAppConfiguration
@Import({TestContext.class})
public class NotificacaoControllerTest {

    @Autowired
    NotificacaoRepository notificacaoRepositoryMock;

    @Before
    public void setUp() {
        Mockito.reset(notificacaoRepositoryMock); // Error >> org.mockito.exceptions.misusing.NotAMockException: Argument should be a mock, but is: class com.sun.proxy.$Proxy55
        this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

Upvotes: 3

Views: 6203

Answers (2)

jfcorugedo
jfcorugedo

Reputation: 10061

As far as I know, you are trying to replace the spring bean with a mock version.

In that case you have to annotate the method that produces your mock with the annotation @Primary, so Spring could choose the mock object by default in each autowired field (of course if it doesn't have any qualifier).

If you're trying to use a Spring context in your test that has some real beans and other mock beans, you have to follow this steps:

  • Create a @Configuration class in your test folder that inject a mock instance of the beans you want to mock
  • Import this configuration class in your test

For instance:

Configuration class that injects the mock

import static org.mockito.Mockito.mock;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import xxx.xxx.xxx.NotificacaoRepository;

@Configuration
public class MockConfigurer {

    @Bean
    @Primary
    public NotificacaoRepository registerMock() {
        return mock(NotificacaoRepository.class);
    }
}

Test class

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {WebAppConfig.class})
@WebAppConfiguration
@Import({MockConfigurer.class})
public class NotificacaoControllerTest {

    //Now the instance injected here should be a mock object
    @Autowired
    private NotificacaoRepository notificacaoRepositoryMock;

    ...
}

Upvotes: 0

Vyncent
Vyncent

Reputation: 1205

This is because Spring create a proxy around your bean.

Try to not inject mock using Spring

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {TestContext.class, WebAppConfig.class})
@WebAppConfiguration
public class NotificacaoControllerTest {

    private MockMvc mockMvc;

    private NotificacaoRepository notificacaoRepositoryMock;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Before
    public void setUp() {
        notificacaoRepositoryMock = Mockito.mock(NotificacaoRepository.class);
        Mockito.reset(notificacaoRepositoryMock);

        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

Upvotes: 2

Related Questions