[JAVA] Contrôleur de cadre de test Spring avec Junit

Public cible

・ Débutants Spring Framework ・ Junit débutant ・ Je veux tester le contrôleur du framework Spring avec Junit! !! !!

Projet ver

・ Cadre Spring 4.1.6 ・ Junit 4.1.2 ・ Servlet 3.1.0 ・ Hamcrest 2.2 ・ Momo c et 3.3.3.

Structure des fichiers

//Couche principale
src.main.java
  |
  +--- jp.co.demo                         
        +--- controller 
        +--- dto
        +--- form
        +--- entity
        +--- mapper
        +--- service
  
//Couche de test
src.test.java
  |
  +--- jp.co.demo                         
  |     +--- controller 
  |
src.test.resources
  |
  +--- META-INF
  |           |
  |           +--- sql
  |                  |
  |                  +--- insert_data.sql //SQL pour créer des données de test
  |
  +--- spring
            |
            +--- mvc-config.xml //Fichier de définition de bean

tester

Fichier exécutable SQL

insert_data.sql



DELETE FROM messages;
DELETE FROM users;

INSERT INTO users(id,account,password,name,branch_id,department_id) VALUES (1,'testuser','$2a$10$i0FlsKe6FiEuViMhclA90uCjCCKeLhtcswz01Rwl9qTIsIY1c.ohO','ALH Taro',1,1);

ALTER TABLE messages MODIFY id int not null; --Réinitialisation automatique de l'incrémentation temporaire pour réinitialiser l'incrémentation automatique
ALTER TABLE messages AUTO_INCREMENT = 1; --Réinitialisation automatique de l'incrément
ALTER TABLE messages MODIFY id int not null auto_increment; --Octroi d'incrément automatique

INSERT INTO messages(title,text,category,user_id, created_date)VALUES('Titre','Texte','Catégorie',1,'2020-05-27 01:02:03'); --3
INSERT INTO messages(title,text,category,user_id, created_date)VALUES('Titre','Texte','Catégorie',1,'2020-05-28 02:03:04'); --4
INSERT INTO messages(title,text,category,user_id, created_date)VALUES('Titre','Texte','Catégorie',1,'2020-05-23 03:04:05'); --1
INSERT INTO messages(title,text,category,user_id, created_date)VALUES('Titre','Texte','Catégorie',1,'2020-05-24 04:05:06'); --2
INSERT INTO messages(title,text,category,user_id, created_date)VALUES('Titre','Texte','Catégorie',1,'2020-05-29 05:06:07'); --5

Test du contrôleur

DemoControllerTest.java



@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration //Contexte prêt à l'emploi
@ContextConfiguration(locations = "classpath:spring/mvc-config.xml") //Spécifiez le fichier de définition de bean à utiliser
@Transactional //Défini pour la restauration après le test
public class DemoControllerTest {

	private MockMvc mockMvc;

	@Autowired
	private WebApplicationContext wac; //Préparer le contexte

	@Autowired
	private JdbcTemplate jdbcTemplate;

	@Before
	public void setUp() {
		executeScript("/META-INF/sql/insert_data.sql"); //Exécution SQL
		mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
	}

	@Test
	public void test_1 Affichage de l'écran d'accueil() throws Exception {
		MvcResult mvcResult = mockMvc.perform(get("/home")) //Comportement de la communication GET avec perform
				.andDo(print()) //Imprimer sur console
				.andExpect(status().isOk()) //Vérifiez le code d'état
				.andExpect(view().name("home")) //La vue correspond-elle?
				.andExpect(model().attributeExists("allUserMessage")) //Vérifiez si le modèle cible existe
				.andExpect(model().attributeExists("userComment")) //Vérifiez si le modèle cible existe
				.andExpect(model().attributeExists("deleteCommentForm")) //Vérifiez si le modèle cible existe
				.andExpect(model().attributeExists("commentForm")) //Vérifiez si le modèle cible existe
				.andExpect(model().attributeExists("userMessageForm")) //Vérifiez si le modèle cible existe
				.andReturn(); //Renvoie le résultat à mvcResult

		ModelAndView mav = mvcResult.getModelAndView();
		int[] expectMessageIdList = { 5, 2, 1, 4, 3 }; //Pour confirmation de commande ascendante

		@SuppressWarnings(value = "unchecked")
		List<UserMessageForm> actualMessageList = ((List<UserMessageForm>) mav.getModel().get("allUserMessage"));

		int expectMessageListSize = 5;
		assertEquals(expectMessageListSize, actualMessageList.size()); //Les données créées correspondent-elles à la taille de la liste du modèle affiché?

		for (int i = 0; i < 5; i++) {
			assertEquals(expectMessageIdList[i], actualMessageList.get(i).getId()); //Le contenu du message est-il dans l'ordre croissant?
		}

	}

	@Test
	public void test_2_1 L'écran de connexion peut-il être affiché?() throws Exception {
		mockMvc.perform(get("/login"))
				.andDo(print())
				.andExpect(status().isOk())
				.andExpect(model().attributeExists("loginForm"));
	}

	@Test
	public void test_2_2 Pouvez-vous vous connecter?() throws Exception {
		LoginForm loginForm = new LoginForm();
		loginForm.setAccount("testuser");
		loginForm.setPassword("password");

		mockMvc.perform(post("/login").flashAttr("loginForm", loginForm))
				.andDo(print())
				.andExpect(view().name("redirect:/home")) //Destination de transition lorsque la connexion est réussie
				.andExpect(status().isFound());
	}

	@Test
	public void test_2_3 Lorsque le mot de passe est incorrect, une erreur est générée et l'écran de connexion s'affiche.() throws Exception {
		LoginForm loginForm = new LoginForm();
		loginForm.setAccount("testuser");
		loginForm.setPassword("Mauvais mot de passe");

		MvcResult mvcResult = mockMvc.perform(post("/login")
				.flashAttr("loginForm", loginForm))
				.andDo(print())
				.andExpect(view().name("login"))
				.andExpect(status().isOk())
				.andExpect(model().attributeHasErrors("loginForm")) //Y a-t-il une erreur dans le modèle?
				.andReturn();

		ModelAndView mav = mvcResult.getModelAndView();
		BindingResult result = (BindingResult) mav.getModel()
				.get("org.springframework.validation.BindingResult.loginForm");

		String actualErrorMessage = result.getFieldError("account").getDefaultMessage();
		String expectErrorMessage = "ID de connexion ou mot de passe incorrect";
		assertThat(expectErrorMessage, is(actualErrorMessage)); //Vérifier le message d'erreur
	}

	@Test
	public void test_2_4 Lorsque vous essayez de vous connecter avec un compte inexistant, une erreur s'affiche à l'écran et l'écran de connexion s'affiche.() throws Exception {
		LoginForm loginForm = new LoginForm();
		loginForm.setAccount("Compte inexistant");
		loginForm.setPassword("password");

		MvcResult mvcResult = mockMvc.perform(post("/login")
				.flashAttr("loginForm", loginForm))
				.andDo(print())
				.andExpect(status().isOk())
				.andExpect(model().attributeHasErrors("loginForm")) //Y a-t-il une erreur dans le modèle?
				.andReturn();

		ModelAndView mav = mvcResult.getModelAndView();
		BindingResult result = (BindingResult) mav.getModel()
				.get("org.springframework.validation.BindingResult.loginForm");

		String actualErrorMessage = result.getFieldError("account").getDefaultMessage();
		String expectErrorMessage = "Le compte n'existe pas";
		assertThat(expectErrorMessage, is(actualErrorMessage)); //Vérifier le message d'erreur
	}

	public void executeScript(String file) {
		Resource resource = new ClassPathResource(file, getClass());

		ResourceDatabasePopulator rdp = new ResourceDatabasePopulator();
		rdp.addScript(resource);
		rdp.setSqlScriptEncoding("UTF-8");
		rdp.setIgnoreFailedDrops(true);
		rdp.setContinueOnError(false);

		Connection conn = DataSourceUtils.getConnection(jdbcTemplate.getDataSource());
		rdp.populate(conn);
	}

}

Impressions

Il s'agit d'un test unitaire du contrôleur jusqu'au dernier, et ne considère pas l'acquisition et le test du résultat du rendu du côté de la vue (et aucun filtre de connexion, etc. n'est appliqué). Il semble que vous pouvez obtenir le résultat du rendu en utilisant HtmlUnit, donc je le listerai dans Qiita à un autre moment.

Les références

Gestion des données de test par Java + Spring (3) [SpringBoot] Comment écrire un test de contrôleur Document officiel du test de printemps

Recommended Posts

Contrôleur de cadre de test Spring avec Junit
Testez le contrôleur avec Mock MVC dans Spring Boot
Tester l'API Web avec junit
[Spring] Test de sortie d'exception du contrôleur
[Compatible JUnit 5] Ecrire un test en utilisant JUnit 5 avec Spring boot 2.2, 2.3
[JUnit 5] Ecrivez un test de validation avec Spring Boot! [Test de paramétrage]
J'ai écrit un test avec Spring Boot + JUnit 5 maintenant
[Java] Tester des méthodes privées avec JUnit
Exemple de code pour le test unitaire d'un contrôleur Spring Boot avec MockMvc
Effectuer un test de confirmation de transaction avec Spring Boot
Le test JUnit 5 Gradle génère une erreur avec l'annotation Lombok
Présentation du test Java automatisé avec JUnit 5 + Gradle
Test de validation de classe de formulaire avec Spring Boot
[Java] Comment tester s'il est nul dans JUnit
[CircleCI 2.0] [Java] [Maven] [JUnit] Agréger les résultats des tests JUnit avec CircleCI 2.0
Comment tester les interruptions pendant Thread.sleep avec JUnit
Test JUnit facile de la version Elasticsearch 2018 avec Embedded-elasticsearch
[Java] Hello World avec Java 14 x Spring Boot 2.3 x JUnit 5 ~
Tester le code à l'aide d'une maquette avec JUnit (centre EasyMock)
Rendre System.out Mock avec Spock Test Framework
Mélanger les cas de test avec JUnit 5 et les méthodes par défaut
Comment effectuer UT avec Excel en tant que données de test avec Spring Boot + JUnit5 + DBUnit
[Spring Framework] Division de la configuration
Prise en charge multilingue de Spring Framework
Test d'intégration avec Gradle
1. Démarrez Spring Framework à partir de 1
Résumé de Spring Framework - À propos de DI
Ressort avec actionneur Kotorin --5
Tester le contenu d'un fichier Excel avec JUnit
[Rails] Test avec RSpec
Test unitaire de l'API Web et test d'intégration avec SpringBoot + Junit5, 4 modèles
Validation personnalisée avec Spring
J'ai créé un domaine api avec Spring Framework. Partie 1
Tester automatiquement avec la jauge
Test de charge avec JMeter
Printemps avec Kotorin ―― 1. INITIALISATION PRINTEMPS
Télécharger avec Spring Boot
MOCK les constructeurs d'autres classes avec Spring MVC + PowerMock + Junit
Créez une application Web Hello World avec Spring Framework + Jetty
Utilisez Spring Test + Mockito + JUnit 4 pour le test unitaire Spring Boot + Spring Retry
[Java] Je souhaite tester l'entrée standard et la sortie standard avec JUnit
Micro service facile avec Spark Framework!
[Notes personnelles] À propos du framework Spring
[Java] Exemple de cas de test JUnit 4
Hello World avec Spring Boot
Configuration Java avec Spring MVC
JUnit 5 échoue avec java.lang.NoSuchMethodError: org.junit.platform.launcher.Launcher.execute
Implémenter GraphQL avec Spring Boot
Spring with Kotorin --- 8. Couche de référentiel
Série de mémos d'auto-apprentissage Spring Framework_1
À propos de l'erreur de contexte Spring Framework
Démarrez avec Spring Boot
Bonjour tout le monde avec Spring Boot!
Spring avec Kotorin --6 Traitement asynchrone
Tester Active Strage avec RSpec
Exécutez LIFF avec Spring Boot
Connexion SNS avec Spring Boot
Flux de contrôleur de vue du modèle de ressort
Téléchargement de fichiers avec Spring Boot
Spring Boot commençant par copie
Ressort avec Kotorin ―― 7. Couche de service