記事投稿Webアプリを自作しています。プログラミングの勉強し始めて1年ちょっとです。
アイコン設定を実装したのですが、ダメもとで書いてみたコードでなぜか
正常に動作しています。(正常に動作しているのはありがたいのですが・・・)原因がわからず、テストコードを書いてみたら予想通りPersonControllerのedit()メソッドのif文内、person.getIcon_file()がNullなのでNullpointerExceptionが発生。
テストではtestEditProfilePostSucccess()メソッド内の.andExpect(model().hasErrors)を.andExpect(status().isOk())にしてくれと言われるんですが、
実際はmodel().hasErrors()にするとテストは正常に動作します。
試しにPersonControllerのeditメソッドのbindingResult.hasErrors()をコメントアウトしてテストをすると
PersonControllerのperson.getIcon_file()がNullやから参照できません、と言われました。
Controllerの仕様は、return"redirect:/person/formなのでテストは.andExpect(status().isFound())になるはずです。
解決したいことは、
・そもそもアプリの動作が上手くいくのはどうしてか?(PersonControllerのedit()メソッドのperosn.getIcon_file()がNullなのでNullPointerExceptionが発生するのでは?)
・(正常に動作しているので、実装が正しいと仮定して)テストはどう改善したら良いか
皆様、どうかご教授お願い致します。
開発環境:Java 8
Spring Boot 2.2.12
My SQL 8.0.1
該当コードは下記
java
1@Entity 2@Data 3public class Person { 4 @Id 5 @GeneratedValue(strategy=GenerationType.AUTO) 6 private Integer id; 7 8 @NotBlank(message="ユーザー名を入力してください") 9 @Size(max=80,message="ユーザー名は80字以内で入力してください") 10 @Column(length=80) 11 private String name; 12 13 private String icon_base64_str; 14 15 @Transient 16 private MultipartFile icon_file; 17 18 @OneToMany(mappedBy="person") 19 private List<Blog> blogs; 20 21@Service 22public class PersonService { 23 @Autowired 24 private PersonRepository personRepository; 25 26 public Person createPerson() { 27 Person person=new Person(); 28 person.setName("名前を設定してください"); 29 personRepository.save(person); 30 return person; 31 } 32 public void updatePerson(Person person) { 33 personRepository.save(person); 34 } 35} 36 37@Controller 38@RequestMapping("/person") 39public class PersonController { 40 @Autowired 41 private PersonService personService; 42 @Autowired 43 private UserService userService; 44 //プロフィール編集 45 @GetMapping("/edit") 46 public String edit(Person person,Model model){ 47 List<Blog> blogs=blogService.getMyBlogs(person); 48 model.addAttribute("blogs",blogs); 49 model.addAttribute("base64icon",person.getIcon_base64_str()); 50 return"person/form"; 51 } 52 @PostMapping("/edit") 53 public String edit(@Valid Person person,BindingResult bindingResult) { 54 if(bindingResult.hasErrors()) { 55 return"person/form"; 56 } 57 if(!person.getIcon_file().isEmpty()) { 58 try { 59 MultipartFile file=person.getIcon_file(); 60 StringBuffer data=new StringBuffer(); 61 String base64=new String(Base64.encodeBase64(file.getBytes()),"ASCII"); 62 data.append("data:image/jpeg;base64,"); 63 data.append(base64); 64 person.setIcon_base64_str(data.toString()); 65 }catch(Exception e) { 66 } 67 } 68 personService.updatePerson(person); 69 return"redirect:/person/index"; 70 }
HTML
1<!DOCTYPE html> 2<html xmlns:th="http://www.thymeleaf.org" 3 xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> 4<head> 5<meta charset="UTF-8"> 6<title>プロフィール編集</title> 7</head> 8<body> 9<p> 10 <a class="return" href="/person/index">一覧に戻る</a> 11</p> 12<form th:action="@{/person/edit}" th:object="${person}" method="post" enctype="multipart/form-data"> 13 <!-- アイコン未設定時 --> 14 <span th:if="${person.icon_base64_str eq null}"> 15 アイコン設定 16 ファイルを選択してください 17 <input type="file" th:field="*{icon_file}"> 18 </span> 19 20 <!-- アイコン設定時 --> 21 <span th:if="${person.icon_base64_str !=null}"> 22 <img th:src="${base64icon}" style="width:100px; height:100px;-moz-border-radius: 50px; 23 -webkit-border-radius: 25px;border-radius: 50px;"><br> 24 アイコン編集 25 ファイルを選択してください 26 <input type="file" th:field="*{icon_file}"> 27 </span> 28 29 <div> 30 名前<br> 31 <input type="text" th:field="*{name}"> 32 <span th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></span> 33 34 </div> 35 <div> 36 <ul> 37 <li th:each="blog:${person.blogs}" th:object="${blog}"> 38 <span th:text="*{title}"></span><br> 39 <span th:text="*{contents}"></span> 40 <a th:href="@{|/person/blog/*{id}/edit|}">編集</a> 41 </li> 42 </ul> 43 </div> 44 <div> 45 <input type="submit" value="編集"> 46 </div> 47</form> 48</body> 49</html>
Java
1@WebMvcTest(PersonController.class) 2public class PersonControllerTest { 3 @Autowired 4 private MockMvc mockMvc; 5 6 @MockBean 7 private PersonService personService; 8 @MockBean 9 private BlogService blogService; 10 @MockBean 11 private CommentService commentService; 12 @MockBean 13 private UserService userService; 14 @MockBean 15 private UserDetailsManager manager; 16 17 private static UserAccount account; 18 private static Blog blog; 19 private static List<Blog> blogs; 20 private static Map<String, Comment> commentMap; 21 22 @BeforeEach 23 public void setUp() { 24 Person person1=new Person(); 25 person1.setName("chikara"); 26 account=new UserAccount(); 27 account.setPerson(person1); 28 when(userService.find("user")).thenReturn(account); 29 30 Person person2=new Person(); 31 person2.setName("minato"); 32 33 blog=new Blog(); 34 blog.setTitle("Spring"); 35 blog.setContents("a"); 36 blog.setPerson(person1); 37 blogs=Arrays.asList(blog); 38 39 commentMap=new HashMap<String, Comment>(); 40 41 Comment comment1=new Comment(); 42 comment1.setBlog(blog); 43 comment1.setPerson(person2); 44 comment1.setCommenting("11"); 45 commentMap.put("1", comment1); 46 47 Comment comment2=new Comment(); 48 comment2.setBlog(blog); 49 comment2.setPerson(person1); 50 comment2.setCommenting("22"); 51 commentMap.put("2", comment2); 52 } 53 @TestConfiguration 54 static class Config implements WebMvcConfigurer{ 55 56 @Override 57 public void addFormatters(FormatterRegistry registry) { 58 registry.addConverter(String.class,Blog.class,id->blog); 59 registry.addConverter(String.class,Person.class,id->account.getPerson()); 60 registry.addConverter(String.class,Comment.class,id->commentMap.get(id)); 61 } 62 } 63 @Test 64 @WithMockUser(roles="USER") 65 public void testEditProfilePostSucccess() throws Exception{ 66 MultiValueMap<String, String> params=new LinkedMultiValueMap<>(); 67 params.add("name", "chikara"); 68 params.add("birthday", "1990-1-1"); 69 params.add("icon_file", "picture.jpg"); 70 mockMvc.perform(post("/person/edit").with(csrf()).params(params)) 71 .andExpect(status().isFound()); 72 }
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/10/25 04:19