3

I'm running into this issue when trying to mock an object of the interface org.springframework.ui.Model. I'm using Mockito 3.5.15 w/Java 8 and JUnit Jupiter. I've tried using both @Mock and Mockito.mock(), globally and inside a method, but get the error regardless. Since initMocks() is deprecated, I am using Mockito.openMocks(). I know that the contents of testGetMenu() aren't causing the error, because I get it even when the method body is empty. The class being tested is a Spring MVC controller.

Stacktrace when mocking:

java.lang.ExceptionInInitializerError
    at org.mockito.internal.exceptions.stacktrace.ConditionalStackTraceFilter.<init>(ConditionalStackTraceFilter.java:17)
    at org.mockito.exceptions.base.MockitoException.filterStackTrace(MockitoException.java:41)
    at org.mockito.exceptions.base.MockitoException.<init>(MockitoException.java:30)
    at org.mockito.exceptions.misusing.MockitoConfigurationException.<init>(MockitoConfigurationException.java:18)
    at org.mockito.internal.configuration.plugins.PluginLoader.loadImpl(PluginLoader.java:66)
    at org.mockito.internal.configuration.plugins.PluginLoader.loadPlugin(PluginLoader.java:24)
    at org.mockito.internal.configuration.plugins.PluginRegistry.<init>(PluginRegistry.java:12)
    at org.mockito.internal.configuration.plugins.Plugins.<clinit>(Plugins.java:11)
    at org.mockito.internal.util.MockUtil.<clinit>(MockUtil.java:24)
    at org.mockito.internal.stubbing.defaultanswers.ReturnsEmptyValues.<init>(ReturnsEmptyValues.java:58)
    at org.mockito.internal.stubbing.defaultanswers.ReturnsMoreEmptyValues.<init>(ReturnsMoreEmptyValues.java:51)
    at org.mockito.internal.stubbing.defaultanswers.ReturnsSmartNulls.<init>(ReturnsSmartNulls.java:40)
    at org.mockito.Answers.<clinit>(Answers.java:43)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at java.lang.Class.getEnumConstantsShared(Class.java:3320)
    at java.lang.Class.enumConstantDirectory(Class.java:3341)
    at java.lang.Enum.valueOf(Enum.java:232)
    at sun.reflect.annotation.AnnotationParser.parseEnumValue(AnnotationParser.java:483)
    at sun.reflect.annotation.AnnotationParser.parseMemberValue(AnnotationParser.java:347)
    at java.lang.reflect.Method.getDefaultValue(Method.java:606)
    at sun.reflect.annotation.AnnotationType.<init>(AnnotationType.java:132)
    at sun.reflect.annotation.AnnotationType.getInstance(AnnotationType.java:85)
    at sun.reflect.annotation.AnnotationParser.parseAnnotation2(AnnotationParser.java:266)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations2(AnnotationParser.java:120)
    at sun.reflect.annotation.AnnotationParser.parseAnnotations(AnnotationParser.java:72)
    at java.lang.reflect.Field.declaredAnnotations(Field.java:1150)
    at java.lang.reflect.Field.declaredAnnotations(Field.java:1148)
    at java.lang.reflect.Field.getAnnotation(Field.java:1120)
    at java.lang.reflect.AccessibleObject.getDeclaredAnnotation(AccessibleObject.java:219)
    at org.junit.platform.commons.util.AnnotationUtils.findAnnotation(AnnotationUtils.java:128)
    at org.junit.platform.commons.util.AnnotationUtils.findAnnotation(AnnotationUtils.java:115)
    at org.junit.platform.commons.util.AnnotationUtils.isAnnotated(AnnotationUtils.java:93)
    at org.junit.platform.commons.util.AnnotationUtils.lambda$findAnnotatedFields$6(AnnotationUtils.java:369)
    at java.util.function.Predicate.lambda$and$0(Predicate.java:69)
    at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:174)
    at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1382)
    at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
    at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
    at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
    at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:499)
    at org.junit.platform.commons.util.ReflectionUtils.findFields(ReflectionUtils.java:1137)
    at org.junit.platform.commons.util.AnnotationUtils.findAnnotatedFields(AnnotationUtils.java:371)
    at org.junit.platform.commons.util.AnnotationUtils.findAnnotatedFields(AnnotationUtils.java:348)
    at org.junit.jupiter.engine.descriptor.ExtensionUtils.registerExtensionsFromFields(ExtensionUtils.java:99)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.prepare(ClassBasedTestDescriptor.java:148)
    at org.junit.jupiter.engine.descriptor.ClassBasedTestDescriptor.prepare(ClassBasedTestDescriptor.java:78)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$prepare$1(NodeTestTask.java:107)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.prepare(NodeTestTask.java:107)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:75)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:141)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: java.lang.NullPointerException
    at org.mockito.internal.configuration.plugins.Plugins.getStackTraceCleanerProvider(Plugins.java:17)
    at org.mockito.internal.exceptions.stacktrace.StackTraceFilter.<clinit>(StackTraceFilter.java:21)
    ... 78 more

AppControllerTest.java

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.ui.Model;

import com.javaduckspizza.OnlineOrderingApplication.common.TypesCache;
import com.javaduckspizza.OnlineOrderingApplication.main.AppController;

@ExtendWith(MockitoExtension.class)
@RunWith(MockitoJUnitRunner.class)
class AppControllerTest {
    @InjectMocks
    AppController appController = new AppController();
    @Mock
    Model model;

    @BeforeEach
    void setUp() throws Exception {
//      model = Mockito.mock(Model.class);
        MockitoAnnotations.openMocks(this); //using because initMocks() is deprecated
    }

    @AfterEach
    void tearDown() throws Exception {
    }

    @Test
    void testGetMenu() {
        String result = appController.getMenu(model);
        assertEquals(result, "/menu.");
        verify(model, times(5)).addAttribute(Mockito.anyString(), Mockito.any());
        verify(model, times(1)).addAttribute(Mockito.anyString(), Mockito.anyInt());
        MockedStatic<TypesCache> mockedTypesCache = Mockito.mockStatic(TypesCache.class);
        mockedTypesCache.verify(Mockito.times(5), () -> TypesCache.getActiveTypesByCategory(Mockito.anyString()));
    }
}

AppController.java

import java.math.BigDecimal;
import java.util.Date;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.ws.rs.GET;
import javax.ws.rs.POST;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.javaduckspizza.OnlineOrderingApplication.common.TypesCache;
import com.javaduckspizza.service.dao.ModifierServiceDao;
import com.javaduckspizza.service.dao.OrderServiceDao;
import com.javaduckspizza.vo.ModifierVo;
import com.javaduckspizza.vo.OrdersVo;
import com.javaduckspizza.vo.PizzaToppingAssociationVo;
import com.javaduckspizza.vo.PizzaVo;

@Controller
@RequestMapping("/")
public class AppController {
    protected Map<PizzaVo, List<PizzaToppingAssociationVo>> mapShoppingCart =
            new HashMap<PizzaVo, List<PizzaToppingAssociationVo>>();

    @GET
    @RequestMapping("/menu")
    public String getMenu(Model model) {
        System.err.println("In AppController.getMenu()");
        addAttributesForMenu(model);
        model.addAttribute("itemCount", mapShoppingCart.size());

        return "/menu.";  //I probably messed up something in the configuration.  If written without / and ., it tries to get WEB-INF/jspmenujsp
    }

    public void addAttributesForMenu(Model model) {
        model.addAttribute("sizes", TypesCache.getActiveTypesByCategory("SIZE"));
        model.addAttribute("crusts", TypesCache.getActiveTypesByCategory("CRST"));
        model.addAttribute("cheeses", TypesCache.getActiveTypesByCategory("CHES"));
        model.addAttribute("sauces", TypesCache.getActiveTypesByCategory("SAUC"));
        model.addAttribute("toppings", TypesCache.getActiveTypesByCategory("TOPP"));
    }
}

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.3.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.javaduckspizza</groupId>
    <artifactId>OnlineOrderingApplication</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>OnlineOrderingApplication</name>
    <description>Online ordering application for Java Ducks Pizza</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.apache.tomcat.embed</groupId>
            <artifactId>tomcat-embed-jasper</artifactId>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-core</artifactId>
            <version>3.5.15</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-inline</artifactId>
            <version>3.5.15</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.mockito</groupId>
            <artifactId>mockito-junit-jupiter</artifactId>
            <version>3.5.15</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>jakarta.ws.rs</groupId>
            <artifactId>jakarta.ws.rs-api</artifactId>
            <version>2.1.6</version>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.7.0</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>5.7.0</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.22.2</version>
            </plugin>
        </plugins>
    </build>
</project>

Stacktrace if I don't mock

java.lang.NoSuchMethodError: org.mockito.Mockito.mockitoSession()Lorg/mockito/session/MockitoSessionBuilder;
    at org.mockito.junit.jupiter.MockitoExtension.beforeEach(MockitoExtension.java:149)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeEachCallbacks$1(TestMethodTestDescriptor.java:154)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeMethodsOrCallbacksUntilExceptionOccurs$5(TestMethodTestDescriptor.java:190)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeMethodsOrCallbacksUntilExceptionOccurs(TestMethodTestDescriptor.java:190)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeEachCallbacks(TestMethodTestDescriptor.java:153)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:71)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:135)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at java.util.ArrayList.forEach(ArrayList.java:1257)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:125)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:135)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:123)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:122)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:80)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:248)
    at org.junit.platform.launcher.core.DefaultLauncher.lambda$execute$5(DefaultLauncher.java:211)
    at org.junit.platform.launcher.core.DefaultLauncher.withInterceptedStreams(DefaultLauncher.java:226)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:199)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:141)
    at org.eclipse.jdt.internal.junit5.runner.JUnit5TestReference.run(JUnit5TestReference.java:98)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
    Suppressed: java.lang.NullPointerException
        at org.mockito.junit.jupiter.MockitoExtension.afterEach(MockitoExtension.java:184)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterEachCallbacks$11(TestMethodTestDescriptor.java:248)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$13(TestMethodTestDescriptor.java:268)
        at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$14(TestMethodTestDescriptor.java:268)
        at java.util.ArrayList.forEach(ArrayList.java:1257)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:267)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAfterEachCallbacks(TestMethodTestDescriptor.java:247)
        at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:143)
        ... 43 more
Rob Evans
  • 2,822
  • 1
  • 9
  • 15
vnavs
  • 51
  • 1
  • 1
  • 8

3 Answers3

0

The use case you want to test is not what @InjectMocks in combination with @Mock is made for. You use this setup whenever you want to mock a collaborator of your class under test.

Let's say your AppController would inject (e.g. via constructor) a UserService to fetch data. For this scenario, you could then use @Mock for the UserService and mock the behavior of this service throughout your whole unit test for your AppController.

The Model is not a collaborator of your AppController, but rather injected by Spring to your method.

In your test scenario, mocking the Model does not make much sense. Rather use @WebMvcTest to start a sliced Spring Context and then use MockMvc to access your endpoint. You can then use verification methods of MockMvc to check the Model, the view name, the response code.

An example of this might look like the following:

@WebMvcTest(DashboardController.class)
class DashboardControllerTest {
 
  @Autowired
  private MockMvc mockMvc;
 
  @MockBean
  private DashboardService dashboardService;
 
  @Test
  public void shouldReturnViewWithPrefilledData() throws Exception {
    when(dashboardService.getAnalyticsGraphData()).thenReturn(new Integer[]{13, 42});
 
    this.mockMvc
      .perform(get("/dashboard"))
      .andExpect(status().isOk())
      .andExpect(view().name("dashboard"))
      .andExpect(model().attribute("user", "Duke"))
      .andExpect(model().attribute("analyticsGraph", Matchers.arrayContaining(13, 42)))
      .andExpect(model().attributeExists("quickNote"));
  }
}

You can find more information in this MockMvc guide.

PS: @RunWith(MockitoRunner.class) is for JUnit 4, you can remove it if you use JUnit Jupiter.

rieckpil
  • 10,470
  • 3
  • 32
  • 56
  • Okay, thanks, this has helped a lot. I should have specified that I am using Spring Boot. The tests are mostly working. I am running into difficulty when trying to post to a method that takes ModelAttributes as parameters. MockMvc's perform() is throwing an illegal state exception because it can't find a "primary or default constructor for long, – vnavs Nov 09 '20 at 22:52
  • please create a new question on Stack Overflow for this as this seems unrelated to your initial question. – rieckpil Nov 10 '20 at 06:04
  • Okay. That makes sense. – vnavs Nov 12 '20 at 15:37
0

Code referenced in my comment above:

AppControllerTest.java


    @Test
    void testAddItem_Attributes() {
        Long crust = Long.valueOf(0L);
        Long sauce = Long.valueOf(1L);
        Long size = Long.valueOf(2L);
        Long cheese = Long.valueOf(3L);

        PizzaToppingAssociationVo ptavBothSides = new PizzaToppingAssociationVo();
        PizzaToppingAssociationVo ptavLeftOnly = new PizzaToppingAssociationVo();
        PizzaToppingAssociationVo ptavRightOnly = new PizzaToppingAssociationVo();

        ptavBothSides.setLeft(true);
        ptavBothSides.setRight(true);
        ptavBothSides.setToppingsId(5L);

        ptavLeftOnly.setLeft(true);
        ptavLeftOnly.setRight(false);
        ptavLeftOnly.setToppingsId(6L);

        ptavRightOnly.setLeft(false);
        ptavRightOnly.setRight(true);
        ptavRightOnly.setToppingsId(8L);

        PizzaToppingAssociationVo [] toppingsArray = {ptavBothSides, ptavLeftOnly, ptavRightOnly};

        try {
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonToppings = objectMapper.writeValueAsString(toppingsArray);
            
            //this line throws the IllegalStateException with these parameters, but not if called with only "/addItem"
            ResultActions ra = mockMvc.perform(MockMvcRequestBuilders.post("/addItem", crust, sauce, size, cheese, jsonToppings));
            ra.andExpect(MockMvcResultMatchers.status().is3xxRedirection());
            ra.andExpect(MockMvcResultMatchers.redirectedUrl("/menu"));
            ra.andExpect(model().attribute("crust", crust));

            Map<String, Object> modelMap = ra.andReturn().getModelAndView().getModel();
            assertEquals(modelMap.size(), 1);
            assert(modelMap.containsKey("itemCount"));
        } catch (Exception e) {
            e.printStackTrace();
            fail();
        }
    }
vnavs
  • 51
  • 1
  • 1
  • 8
0

In most cases this a dependency issue.

I faced same issue and my issue was the I was using the wrong version of the JDK. Mine was 19 while I should have used v 11.

Give it a try. :)

Tamer Awad
  • 392
  • 7
  • 10