次のことが理解されています。
Expression<Func<string, bool>> first = x => x.Length == 4;
Expression<Func<string, bool>> second = x => x.Length == 4;
Console.WriteLine(first.Equals(second)); // Output is "False"
ただし、各式の文字列を調べると、等しいことがわかります。
Expression<Func<string, bool>> first = x => x.Length == 4;
Expression<Func<string, bool>> second = x => x.Length == 4;
Console.WriteLine(first.ToString().Equals(second.ToString())); // Output is "True"
このアイデアは、さまざまな投稿の集大成でした...
http://www.codethinked.com/Comparing-Simple-Lambda-Expressions-With-Moq Expression<Func<T, bool>> がパラメーターとして渡される メソッドを Moq 化する 特定の linq 式 (moq )
意図:
次のようなリポジトリ パターンを使用して MVC アプリケーションを作成しています。
public class MyController : Controller
{
public Repository.IRepository Repository { get; set; }
public MyController()
{
this.Repository = new Repository.CommonRepository();
}
public MyController(Repository.IRepository repository)
{
this.Repository = repository;
}
[HttpPost]
public ActionResult Create(Domain.Common.Object1 o1)
{
if (ModelState.IsValid)
{
// Additional validation
o1.Name = o1.Name.Trim();
if (this.Repository.Any<Domain.Common.Object1>(a => a.Name.ToLower() == plant.Name.ToLower()))
this.ModelState.AddModelError("Name", "Duplicate found.");
}
if (ModelState.IsValid)
{
var entity = this.Repository.Add(o1);
if (Request.IsAjaxRequest())
return this.Json(new { Completed = true, Id = entity.Id });
return RedirectToAction("Details", new { id = entity.Id });
}
if (Request.IsAjaxRequest())
return PartialView("_Create", o1);
return View("Create", o1);
}
}
リポジトリは、ドメインと同様に完全に別のプロジェクトです。私のリポジトリ コードは、1 つのリポジトリを使用してジェネリックに基づいて任意のオブジェクトをクエリできるように設定されています。
public IQueryable<T> GetAll<T>() where T : AbstractEntity
{
return this.DbContext.Set<T>();
}
注: AbstractEntity は、すべての POCO オブジェクトが継承するドメイン抽象クラスです。
Moq を使用してコントローラーの単体テストを行う場合は、すべて問題ありません。
[TestMethod]
public void Create_Post_DuplicateNameAddsError()
{
// Arrange
var repository = new Mock<Repository.IRepository>();
repository.Setup(a => a.Any<Domain.Common.Object1>(It.IsAny<System.Linq.Expressions.Expression<Func<Domain.Common.Object1, bool>>>()))
.Returns(true);
var controller = ControllerFactory<MyController>.GetController();
controller.Repository = repository.Object;
var model = new Domain.Common.Object1()
{
Id = Guid.NewGuid()
,
Name = "Name"
};
// Act
var result = controller.Create(model) as ViewResult;
// Assert
Assert.IsFalse(controller.ModelState.IsValid);
Assert.IsNotNull(result);
Assert.AreEqual("Create", result.ViewName, false);
Assert.AreEqual(model, result.Model);
}
注: ControllerFactory は、Request、Response、User、Request.Headers などの特定のプロパティが入力されたコントローラーを生成する方法です...
これが失敗するのは、 IRepository.Any(predicate) を複数回使用する必要がある場合、または複数回呼び出される式を使用するメソッドを使用する必要がある場合です。ある場合は true、別の場合は false と言う必要があります。式の文字列が一致した場合、これは問題にはなりませんが、すべてが異なるプロジェクトにあるため、式の文字列は次のようになります。
a => (a.Name.ToLower() == value(foo.Web.Tests.Controllers.Object1ControllerTests+<>c__DisplayClass3).ob1.Name.ToLower())
a => (a.Name.ToLower() == value(foo.Controllers.MyController+<>c__DisplayClass1).ob1.Name.ToLower())
違いは値関数にあります。正規表現からのマッチングを試みましたが、これは機能しますが、すべての .<>() をエスケープする必要があるため見苦しく、維持が非常に困難です。
Matt Meber の Expression Equality Comparerを使用してみましたが、その値関数のために等しくありません (私の信念)。
提案?