miso_soup3 Blog

主に ASP.NET 関連について書いています。

AutoMapper + ViewModel In MVC その2

MVCで書くときのポイント

その2です。

マッピングをテストする

Mapper.AssertConfigurationIsValid();

AutoMapperを利用する時は、必ずこれを書くべきだと思います。
マッピングされないプロパティが存在すると、
AutoMapperConfigurationException の例外を飛ばしてくれます。

The following 1 properties on MvcApplication5.ViewModels.StudentView are not mapped: 
	Names
Add a custom mapping expression, ignore, or rename the property on MvcApplication5.Models.Student.

↑これは、StudentViewのNamesがマッピングされていないときのメッセージ。

Namesプロパティは無視してくれ!という場合は、
以下のように書けば、例外は飛びません。

Mapper.CreateMap<Student, StudentView>()
	.ForMember(
		dst => dst.Names,
		opt => opt.Ignore());

AssertConfigurationIsValid()メソッドは、単体テスト、または実装コードの
設定の後に書いてもよいかと思います。

このメソッドを書くことで、

  • AutoMapperのルールに基づいて、プロパティが定義されている。
  • .ForMemberや、CustomValueResolverなどで、独自のマッピング方法が定義されている。
  • Ignore() で"無視"と定義されている。

などが保証されます。

詳しくは、本家に。
https://github.com/AutoMapper/AutoMapper/wiki/Configuration-validation

マッピングを利用している処理のテストの仕方

AutoMapperを利用している層、たとえばControllerの次の処理を、
どうテストするか・・・なんですが。

マッピングに依存しない方法

ASP.NET MVC, TDD and AutoMapper
↑ここの記事のように、マッピング処理への依存を
取り外すし、テストする際にはモックを利用することが、
正しい方法のように思います。

・・・が、

マッピングに依存する方法
[SetUp]
public void Setup()
{
  Mapping.AutoMapperBootstrapper.Configure();
}

とかいて、マッピングに依存してテストを行う、
という方法もあります。

うーん?

TDDとしては前者の方が正しいと思いますが・・・、
私は今までを含め、これからも後者の方法で書いていくと思います。
まずいでしょうか・・・

何をモックとして扱うべきなのか、まだちゃんとした答えがわかりません・・・。

マッピングは他のケースでも利用できる

AutoMapperについての記事は、EntityからViewModelへ詰め直す場合の例が多いですが、
Mapperという名のもと、他のケースでもどんどん利用してよいと思います。

たとえば、Controllerの編集Actionの時。

public ActionResult Edit(StudentView model)
{
	var request = new EditStudentRequest();
	request.Name = model.Name;
	request.Number = model.Number;
	request.Note = model.Note;

	_studentService.EditStudent(request);
	return View();
}

これを

public ActionResult Edit(StudentView model)
{
	EditStudentRequest request = model.ToEditStudentRequest();
	_studentService.EditStudent(request);
	
	return View();
}

・・・なふうにしてしまうなど。
(.ToEditStudentRequest()は拡張メソッドで、Map<>()を呼んでいます。)

Controller層と、Service層のやりとりの翻訳家です。

他、いろんな層でも利用し、各層にAutoMapperBootstrapperが存在している、
とかもおもしろいと思います。
(名前には注意ですが)

おまけ

上記でリンクを貼ったサイト、
ASP.NET MVC, TDD and AutoMapper
ここのテストの書き方に感動しました。