Ожидаемое состояние: <200>, но было: <404> в spring

У меня есть этот класс:

    package controllers;

    import static org.junit.Assert.*;
    import static org.mockito.Mockito.mock;
    import static org.mockito.Mockito.times;
    import static org.mockito.Mockito.verify;
    import static org.mockito.Mockito.when;

    import java.util.HashSet;

    import org.junit.Before;
    import org.junit.Test;
    import org.junit.runner.RunWith;
    import org.mockito.InjectMocks;
    import org.mockito.Mock;
    import org.mockito.MockitoAnnotations;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.test.context.ContextConfiguration;


    import org.springframework.ui.Model;
    import org.springframework.web.context.WebApplicationContext;

    import com.epam.hhsystem.model.candidate.Candidate;
    import com.epam.hhsystem.services.CandidateService;
    import com.epam.hhsystem.web.controllers.CandidateMenuController;
    import org.springframework.test.context.web.WebAppConfiguration;
    import org.springframework.test.context.junit4.*;
    import org.springframework.test.web.servlet.MockMvc;
    import org.springframework.test.web.servlet.ResultActions;
    import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
    import org.springframework.test.web.servlet.setup.MockMvcBuilders;


    import org.springframework.test.web.servlet.request.*;

    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
    import static org.hamcrest.Matchers.*;
    import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
    import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;


    @ContextConfiguration(locations = { "classpath:/test/BeanConfig.xml" })
    @RunWith(SpringJUnit4ClassRunner.class)
    @WebAppConfiguration
    public class CandidateControllerTest {

        @Mock(name = "candidateService")
        private CandidateService candidateService;

        @InjectMocks
        private CandidateMenuController candidateMenuController = new CandidateMenuController();

        @Autowired
        WebApplicationContext wac;

        MockMvc mockMvc;

        @Before
        public void before() {
            MockitoAnnotations.initMocks(this);
              this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build();

        }
@Test 
    public void testgoToCandidateMenuMockMvc() throws Exception { 
        //MockHttpServletRequestBuilder request = MockMvcRequestBuilders.get("/goToCandidateMenu");


        MockHttpServletRequestBuilder request = MockMvcRequestBuilders.get("/goToCandidateMenu");
        ResultActions result = mockMvc.perform(request);
        result.andExpect(status().isOk());
     }
}

Когда я его выполню, я вижу:

java.lang.AssertionError: Status expected:<200> but was:<404>
at org.springframework.test.util.AssertionErrors.fail(AssertionErrors.java:60)
at org.springframework.test.util.AssertionErrors.assertEquals(AssertionErrors.java:89)
at org.springframework.test.web.servlet.result.StatusResultMatchers$5.match(StatusResultMatchers.java:549)
at org.springframework.test.web.servlet.MockMvc$1.andExpect(MockMvc.java:141)
at controllers.CandidateControllerTest.testgoToCandidateMenuMockMvc(CandidateControllerTest.java:104)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:74)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:83)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:72)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:231)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:88)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:71)
at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:174)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)

Код контроллера:

@Controller
public class CandidateMenuController extends AbstractController {
...
@RequestMapping("/goToCandidateMenu")
    public String goToCandidateMenu() {
        return "candidateMenu";
    }
...
}

Можете ли вы помочь мне решить мою проблему?

UPDATE

BeanConfig.xml:

 <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
        xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
        xmlns:util="http://www.springframework.org/schema/util"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
            http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
            http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
            http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

        <!-- Включаем опцию использования конфигурационных аннотаций (@Annotation-based configuration)-->
        <context:annotation-config />


        <context:component-scan base-package="com.epam.hhsystem.jpa" />
        <context:component-scan base-package="com.epam.hhsystem.services" />

        <!-- Файл с настройками ресурсов для работы с данными (Data Access Resources) -->
        <import resource="data.xml" />

    </beans>

data.xml

<?xml  version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee" xmlns:lang="http://www.springframework.org/schema/lang"
    xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:util="http://www.springframework.org/schema/util"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/lang http://www.springframework.org/schema/lang/spring-lang.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

<!-- Настраивает управление транзакциями с помощью аннотации @Transactional -->
    <tx:annotation-driven transaction-manager="transactionManager" />

    <!-- Менеджер транзакций -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate4.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- Непосредственно бин dataSource -->
    <bean id="dataSource"
        class="org.springframework.jdbc.datasource.DriverManagerDataSource"
        p:driverClassName="com.microsoft.sqlserver.jdbc.SQLServerDriver"
        p:url="jdbc:sqlserver://10.16.9.52:1433;databaseName=hhsystemTest;"
        p:username="userNew" 
        p:password="Pass12345" />

    <!-- Настройки фабрики сессий Хибернейта -->
    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="configLocation">
            <value>classpath:test/hibernate.cfg.xml</value>
        </property>

        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</prop>
                <prop key="hibernate.connection.charSet">UTF-8</prop>
<!--                <prop key="hibernate.hbm2ddl.auto">create-drop</prop> -->
        </props>
        </property>
    </bean>

</beans>

Ответ 1

Ваша тестовая установка неверна, вы не правильно инициализируете MockMvc и это явно указано в справочном руководстве. FIrst всего, что у вас есть дважды код инициализации, и вы не оцениваете результат вызова метода build. Таким образом, вы в основном остаетесь с пустым MockMvc объектом.

@Before
public void before() {
    MockitoAnnotations.initMocks(this);
    MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build();
    MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build();
}

Должно быть

@Before
public void before() {
    MockitoAnnotations.initMocks(this);
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build();
}

Как указано, это объясняется в справочном руководстве.

Ответ 2

Я считаю, что вы просто не включили <mvc:annotation-driven> в свой beanconfig.xml, и поэтому ваши классы @Controller просто не регистрируются.

Добавьте это

<mvc:annotation-driven></mvc:annotation-driven>

Ответ 3

Это мое рабочее решение. Надеюсь, поможет.

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
@WebAppConfiguration
public class SimpleTest  {

private MockMvc mockMvc;

@Autowired
private WebApplicationContext webApplicationContext;

@Before
public void setup() throws Exception {
    mockMvc = webAppContextSetup(webApplicationContext)
            .build();
    }

@Test
public void test() throws Exception {        
    mockMvc.perform(get("/simple")
            .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().is(200));
    }
}

Ответ 4

В моем случае я пропустил приведенную ниже аннотацию и получал эту ошибку.

@WebMvcTest(UserStatsController.class)
public class UserStatsControllerTest {
  ..
}

Обратите внимание, что класс контроллера, а не тест. Также убедитесь, что вы загружаете другой класс, используя @ContextConfiguration (НЕ тест), а не загружаете тестовый класс.

Ответ 5

Я добавил эту аннотацию в класс конфигурации и заработал ее:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigWebContextLoader.class)
@WebAppConfiguration
public class ResourceTest {

   ...

   @Configuration
   @EnableWebMvc
   @ComponentScan( basePackages = { "..." } )
   static class ContextConfiguration {
   }
}

Ответ 6

В том случае, если вы делаете действительно глупую опечатку "собираюсь быстро для вашего же блага", как я, убедитесь, что ваш тестовый класс контроллера НЕ имеет того же имени, что и сам класс контроллера. Большинство людей знают это, но вы можете попасть в то же самое состояние ошибки, имена идентичны, и это может быть не сразу понятно почему. Чтобы уточнить, убедитесь, что вы не делаете это:

Имя контроллера: MyController
Имя тестового класса: MyController

Это может привести к сбою ваших тестов MockMvc со статусом 404... что не очень очевидно.
Наименование [очевидно] должно быть больше похоже на:

Имя контроллера: MyController
Имя тестового класса: MyControllerTest

Ответ 7

Первым делом проверьте, правильно ли настроен контроллер или реализован в вашем тестовом классе.