質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
NullPointerException

null値の参照型変数を参照しようとした場合に投げられる、Javaにおける例外のひとつです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

Q&A

解決済

1回答

1779閲覧

NullPointerExceptionが発生しないのはなぜですか?

chikara

総合スコア6

NullPointerException

null値の参照型変数を参照しようとした場合に投げられる、Javaにおける例外のひとつです。

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Spring

Spring Framework は、Javaプラットフォーム向けのオープンソースアプリケーションフレームワークです。 Java Platform上に、 Web ベースのアプリケーションを設計するための拡張機能が数多く用意されています。

ユニットテスト

ユニットテストは、システムのテスト手法の一つで、個々のモジュールを対象としたテストの事を指します。対象のモジュールが要求や性能を満たしているか確認する為に実行します。

Spring Boot

Spring Bootは、Javaのフレームワークの一つ。Springプロジェクトが提供する様々なフレームワークを統合した、アプリケーションを高速で開発するために設計されたフレームワークです。

1グッド

0クリップ

投稿2021/10/11 04:35

編集2021/10/14 04:49

記事投稿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 }
nulltemp👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

・そもそもアプリの動作が上手くいくのはどうしてか?(PersonControllerのedit()メソッドのperosn.getIcon_file()がNullなのでNullPointerExceptionが発生するのでは?)

適当にMultipartFileで検索すると以下がヒットしました。

https://javazuki.com/articles/spring-mvc-and-boot-file-upload.html

要はHTMLのフォーム内にfileのフィールドがあれば(実際にファイルが指定されていなくても)MultipartFileはnullにはならないということなんだと思います。NullPointerExceptionが発生しないのは今回提示されているHTMLにfileフィールドが設定されているからではないでしょうか?試しにfileフィールドを消してみれば違う結果になるかもしれません(試していないので、ならなかったらすみません)。

・(正常に動作しているので、実装が正しいと仮定して)テストはどう改善したら良いか

すみません、こちらはちょっと目的をうまく理解できなかった(どういうテストが書きたかったのかが分からなかった)のでうまく回答できませんでした。
ただ以下は少し気になりました。

java

1MultiValueMap<String, String> params=new LinkedMultiValueMap<>(); 2params.add("name", "chikara"); 3params.add("birthday", "1990-1-1"); 4params.add("icon_file", "picture.jpg");

なんとなく/person/editのPOSTメソッドの正常系テストをやりたかったのかなと思ったんですが、このやり方だとそもそも文字列しかPOST出来ておらず、ファイルをPOST出来ていないのではないでしょうか?
以下の下の方に値とファイルを同時にPOSTするときのテストコードがありますが、ちょっと試したわけではないので何とも言えないのと、そもそもコードがちょっと見辛いのであまり参考にならないかもしれません。

https://www.fixes.pub/program/240884.html

一応Springの公式もファイルアップロードのテスト例を公開したりしてました。

https://spring.pleiades.io/guides/gs/uploading-files/

いずれにせよMultipartFile junitとかで検索してみて、一度他のテストを参考にしてみるのがいいかもしれません。

投稿2021/10/16 10:11

nulltemp

総合スコア40

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chikara

2021/10/25 04:19

遅くなってごめんなさい! 上記の記事は一度試したことあったのですが、今回もう一度試してみたら 上手くいきました!! testEditProfilePostSucccess()に MockMultipartFile multipartFile=new MockMultipartFile("icon_file","test.txt","text/plain","Spring Framework".getBytes());を追加して、 mockMvc.perform(multipart("/person/edit").file(multipartFile).with(csrf()).params(params)).andExpect(status().isFound()); に変更したらいけました! ありがとうございます!!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問