我花了几天时间寻找解决方案,该解决方案允许我模拟由 Expression<Func<T, bool>>
参数化的方法。 。我发现this 。但不幸的是,当我想使用字符串参数测试服务方法时,它不起作用,例如:public IEnumerable<Person> FindByName(string name)
,如下所示:
using System;
using System.Diagnostics;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
namespace UnitTestProject
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var mock = new Mock<IRepository<Person>();
mock.Setup(r => r.Find(AreEqual<Person>(p => p.FirstName.Equals("Justin")))).Returns(new[]
{
new Person {FirstName = "Justin", LastName = "Smith"},
new Person {FirstName = "Justin", LastName = "Quincy"}
});
var personService = new PersonService(mock.Object);
Person[] justins = personService.FindByName("Justin").ToArray();
Person[] etheredges = personService.FindByName("Etheredge").ToArray();
Debugger.Break();
}
static Expression<Func<T, bool>> AreEqual<T>(Expression<Func<T, bool>> expr)
{
return Match.Create<Expression<Func<T, bool>>>(t => t.ToString() == expr.ToString());
}
}
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public interface IRepository<T>
{
IEnumerable<T> Find(Expression<Func<Person, bool>> predicate);
}
public class PersonService
{
readonly IRepository<Person> _repository;
public PersonService(IRepository<Person> repository)
{
_repository = repository;
}
public IEnumerable<Person> FindByName(string name)
{
return _repository.Find(p => p.FirstName.Equals(name));
}
}
}
当调试器中断时,我期望数组 justins
将包含上面列出的两项和数组 etheredges
将不包含任何项目。实际上它们都是空数组。我怀疑它发生是因为 FindByName
方法中,字符串不是直接提供的,而是通过变量 name
提供的.
你知道如何解决这个问题吗?
最佳答案
假设您只想测试服务的 Find
逻辑(并且您信任 LINQ :-)),您可以做的就是编译传入的 Expression
谓词并在假存储库中执行表达式(即 pred => fakePeople.Where(pred.Compile()));
):
[TestMethod]
public void TestMethod1()
{
var mock = new Mock<IRepository<Person>>();
var fakePeople = new[]
{
new Person {FirstName = "Justin", LastName = "Smith"},
new Person {FirstName = "Justin", LastName = "Quincy"},
new Person {FirstName = "Joe", LastName = "Bloggs"}
};
mock.Setup(r => r.Find(It.IsAny<Expression<Func<Person, bool>>>()))
.Returns<Expression<Func<Person, bool>>>(
pred => fakePeople.Where(pred.Compile()));
var personService = new PersonService(mock.Object);
var searchForJustins = personService.FindByName("Justin");
Assert.AreEqual(2, searchForJustins.Count());
Assert.IsTrue(searchForJustins.Any(_ => _.LastName == "Quincy")
&& searchForJustins.Any(_ => _.LastName == "Smith"));
var searchForEtheredges = personService.FindByName("Etheredge");
Assert.IsFalse(searchForEtheredges.Any());
}
次要,但存储库代码本身无法编译 - 我假设您有一个通用的存储库模式:
public interface IRepository<T>
{
IEnumerable<T> Find(Expression<Func<T, bool>> predicate);
}
public class PersonService
{
readonly IRepository<Person> _repository;
public PersonService(IRepository<Person> repository)
{
_repository = repository;
}
public IEnumerable<Person> FindByName(string name)
{
return _repository.Find(p => p.FirstName.Equals(name));
}
}
关于c# - 模拟存储库和测试参数化服务方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23251512/