[英]Testing expression tree method via Moq not using expression logic
The problem: running the code outright creates the proper filtering, and my unit test is not filtering at all (returning all records in the mocked repository). 问题:直接运行代码会创建正确的过滤条件,而我的单元测试根本就没有过滤条件(返回模拟存储库中的所有记录)。
I can't tell if having the expression logic in the test is screwing something up or what, but no matter the criteria I set, the mocked repository is not filtered on ad I can back "all" records. 我无法判断测试中的表达逻辑是否搞砸了什么,但无论我设定的标准如何,都不会在我可以支持“所有”记录的广告上过滤模拟存储库。 This works 100% from the service layer calling it, but not in tests.
从服务层调用它可以100%起作用,但在测试中不起作用。
Edit: sorry for the formatting of the code, I couldn't get it any better. 编辑:对不起,代码的格式,我无法得到更好的结果。
Code : 代码 :
public abstract class EFRepository<T> : IRepository<T> where T : BaseEFModel {
public IUnitOfWork UnitOfWork { get; set; }
private IDbSet<T> _objectset;
private IDbSet<T> ObjectSet
{
get { return _objectset ?? (_objectset = UnitOfWork.Context.Set<T>()); }
}
public virtual IQueryable<T> WhereInternal(Expression<Func<T, bool>> expression)
{
return ObjectSet.Where(expression);
} }
implementation: 执行:
public class DoNotSolicitRepo : EFRepository<DoNotSolicit>, IDoNotSolicitRepo {
private readonly RestUnitOfWork worker;
public DoNotSolicitRepo(RestUnitOfWork _worker)
{
worker = _worker;
}
public IList<DNSContract> SelectWithCriteria(DNS_Search search)
{
// create the where clause
Expression<Func<DoNotSolicit, bool>> whereClause = c => (
(String.IsNullOrEmpty(search.FirstName) || c.FirstName.StartsWith(search.FirstName)) &&
(String.IsNullOrEmpty(search.LastName) || c.LastName.StartsWith(search.LastName)) &&
(String.IsNullOrEmpty(search.Address1) || c.Address1.Contains(search.Address1)) &&
(String.IsNullOrEmpty(search.Address2) || c.Address2.Contains(search.Address2)) &&
(String.IsNullOrEmpty(search.City) || c.City.Contains(search.City)) &&
(String.IsNullOrEmpty(search.State) || c.State.Equals(search.State)) &&
(String.IsNullOrEmpty(search.Zip5) || c.Zip.Equals(search.Zip5)) &&
(String.IsNullOrEmpty(search.Phone) || c.Phone.Equals(search.Phone)) &&
(String.IsNullOrEmpty(search.Email) || c.Email.Equals(search.Email))
);
using (var scope = worker)
{
scope.Register(this);
var resultList = WhereInternal(whereClause).ToList();
Mapper.CreateMap<DoNotSolicit, DNSContract>()
.ForMember(dest => dest.PartnerCode, opt => opt.Ignore())
.ForMember(dest => dest.PartnerDescription, opt => opt.Ignore())
.ForMember(dest => dest.DoNotSolicitReason, opt => opt.Ignore())
.ForMember(dest => dest.SaveDate, opt => opt.Ignore())
.ForMember(dest => dest.InsertDT, opt => opt.Ignore());
var returnObj = Mapper.Map<IList<DoNotSolicit>, IList<DNSContract>>(resultList);
return returnObj.FriendlySaveDates();
}
} }
Test : 测试 :
base: 基础:
public abstract class BaseEFUnitFixture<T> where T : BaseEFModel {
protected Mock<EFRepository<T>> mockedEFRepo = new Mock<EFRepository<T>>();
public Mock<EFRepository<T>> MockedEFRepositiory()
{
var t = new List<T>();
mockedEFRepo.Setup(x => x.AddInternal(It.IsAny<T>())).Callback((T e) => t.Add(e));
mockedEFRepo.Setup(x => x.AddInternal(It.IsAny<List<T>>())).Callback((IList<T> le) => t.AddRange(le));
mockedEFRepo.Setup(x => x.AllInternal()).Returns(t.AsQueryable());
mockedEFRepo.Setup(x => x.WhereInternal(It.Is<Expression<Func<T, bool>>>(y => y != null))).Returns(t.AsQueryable());
return mockedEFRepo;
}
} }
implementation: 执行:
[TestFixture] public class DNSRepoTest : BaseEFUnitFixture<DoNotSolicit> {
private readonly List<DoNotSolicit> list = new List<DoNotSolicit>();
private class Search
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip5 { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
}
private Expression<Func<DoNotSolicit, bool>> SearchBuilder(Search search)
{
// same as repo logic
Expression<Func<DoNotSolicit, bool>> whereClause = c => (
(String.IsNullOrEmpty(search.FirstName) || c.FirstName.StartsWith(search.FirstName)) &&
(String.IsNullOrEmpty(search.LastName) || c.LastName.StartsWith(search.LastName)) &&
(String.IsNullOrEmpty(search.Address1) || c.Address1.Contains(search.Address1)) &&
(String.IsNullOrEmpty(search.Address2) || c.Address2.Contains(search.Address2)) &&
(String.IsNullOrEmpty(search.City) || c.City.Contains(search.City)) &&
(String.IsNullOrEmpty(search.State) || c.State.Equals(search.State)) &&
(String.IsNullOrEmpty(search.Zip5) || c.Zip.Equals(search.Zip5)) &&
(String.IsNullOrEmpty(search.Phone) || c.Phone.Equals(search.Phone)) &&
(String.IsNullOrEmpty(search.Email) || c.Email.Equals(search.Email))
);
return whereClause;
}
[TestFixtureSetUp]
public void Init()
{
list.Add(new DoNotSolicit
{
DoNotSolicitID = 4,
FirstName = "nunit",
Origination = "testing"
});
mockedEFRepo = MockedEFRepositiory();
mockedEFRepo.Object.AddInternal(list);
}
[Test]
public void SelectWithCriteria_FirstNameMatch()
{
var clause = SearchBuilder(new Search{FirstName = "test"});
var results = mockedEFRepo.Object.WhereInternal(clause).ToList();
Assert.IsNotNull(results);
Assert.IsTrue(results.Count < mockedEFRepo.Object.AllInternal().Count());
Assert.IsTrue(results.Count > 0);
} }
You are wrong with your approach in general. 一般来说,您的方法是错误的。 What you do you mock the class that you test - it is incorrect.
您在嘲笑您测试的类-这是不正确的。 You should only mock something external to the class you are testing - because what mocking does is pretty much replacing the functionality with of mocked object with empty stubs.
您应该只对要测试的类外部的东西进行模拟-因为模拟所做的几乎是用空存根替换模拟对象的功能。 If it's mocked it doesn't work or work as the mock is configured.
如果被模拟,则在配置模拟时它不起作用或不起作用。
I see no reason why you would want to test the mocked class, as in this case what you are testing is not the class functionality/code but the way you configured your mock. 我认为没有理由要测试模拟的类,因为在这种情况下,您要测试的不是类功能/代码,而是配置模拟的方式。
It's quite hard to understand what code do you want your test method to test. 很难理解您想要您的测试方法进行测试的代码。 I would suggest doing the dependency injection to separate the actual data repository (which could be mocked with specific data/methods) and the class that contains logic (like selecting the first match).
我建议进行依赖注入以分离实际的数据存储库(可以用特定的数据/方法模拟)和包含逻辑的类(例如选择第一个匹配项)。 Pass mocked repository in the constructor of your logic class and test it asserting the expected behavior.
在您的逻辑类的构造函数中传递模拟的存储库,并测试该存储库以断言预期的行为。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.