J'ai cette classe:
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());
}
}
Quand je l'exécute, je vois:
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)
Code du contrôleur:
@Controller
public class CandidateMenuController extends AbstractController {
...
@RequestMapping("/goToCandidateMenu")
public String goToCandidateMenu() {
return "candidateMenu";
}
...
}
Pouvez-vous m'aider à résoudre mon problème?
MISE À JOUR
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>
Votre configuration de test est incorrecte, vous n'initialisez pas correctement le MockMvc
et cela est clairement indiqué dans le guide de référence. Tout d'abord, vous avez deux fois le code d'initialisation et vous n'évaluez pas le résultat de l'appel à la méthode build
. Il vous reste donc essentiellement un objet MockMvc
vide.
@Before
public void before() {
MockitoAnnotations.initMocks(this);
MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build();
MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build();
}
Devrait être
@Before
public void before() {
MockitoAnnotations.initMocks(this);
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).dispatchOptions(true).build();
}
Comme indiqué, tout est expliqué dans le guide de référence .
Je pense que vous n'avez tout simplement pas activé <mvc:annotation-driven>
dans votre beanconfig.xml
et donc votre @Controller
les classes ne sont tout simplement pas enregistrées.
Ajoute ça
<mvc:annotation-driven></mvc:annotation-driven>
Ceci est ma solution de travail. J'espère que ça aide.
@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));
}
}
Dans mon cas, je manquais l'annotation ci-dessous et j'obtenais cette erreur.
@WebMvcTest(UserStatsController.class)
public class UserStatsControllerTest {
..
}
Notez que la classe du contrôleur et PAS le test. Assurez-vous également que si vous chargez une autre classe en utilisant @ContextConfiguration (PAS le test), ne chargez pas la classe de test.
J'ai ajouté ces annotations à la classe de configuration et je l'ai travaillé:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(loader = AnnotationConfigWebContextLoader.class)
@WebAppConfiguration
public class ResourceTest {
...
@Configuration
@EnableWebMvc
@ComponentScan( basePackages = { "..." } )
static class ContextConfiguration {
}
}
Mon problème était que je n'avais pas @ComponentScan () c'était assez embarrassant. C'était également difficile à trouver. J'ai moi-même négligé ma SpringBootApplication.
Dans le cas où vous faites une faute de frappe "aller trop vite pour votre bien" comme je l'ai fait, assurez-vous que votre classe de test de contrôleur n'a PAS le même nom que la classe de contrôleur elle-même. La plupart des gens le savent, mais vous pouvez vous retrouver dans cette même condition d'erreur, les noms sont identiques, et il se peut que je ne sache pas immédiatement pourquoi. Pour clarifier davantage, assurez-vous de NE PAS FAIRE CECI:
Nom du contrôleur: MyController
Nom de la classe de test: MyController
Cela peut entraîner l'échec de vos tests MockMvc avec le statut 404 ... ce qui n'est pas très évident.
Le nom [évidemment] devrait ressembler davantage à:
Nom du contrôleur: MyController
Nom de la classe de test: MyControllerTest