C# 使用私有setter测试属性

C# 使用私有setter测试属性,c#,unit-testing,moq,encapsulation,access-modifiers,C#,Unit Testing,Moq,Encapsulation,Access Modifiers,当前,在我的项目的一部分中,存在如下域对象: public class Address { public virtual string HouseName { get; set; } public virtual string HouseNumber { get; set; } public virtual string RoadName { get; set; } public virtual string Postcode { get; set; }

当前,在我的项目的一部分中,存在如下域对象:

public class Address
{
    public virtual string HouseName { get; set; }

    public virtual string HouseNumber { get; set; }

    public virtual string RoadName { get; set; }

    public virtual string Postcode { get; set; }

    public virtual string District { get; private set; }
}
District属性是数据库中的计算列。由于数据访问提供商(实体框架)的要求,需要一个私有集。这在正常的程序流程中很好,因为当在数据库中保存/更新地址记录时,它会被更新,因此不需要设置地区

我要测试的方法如下所示:

public IEnumerable<House> GetHousesWithinSameDistrict (int addressId)
{
    var addressToMatch = _addressRepository
      .FirstOrDefault(address => address.Id == addressId)

    return _houseRepository
      .Where(house => house.Address.District == addressToMatch.District)
}
public IEnumerable GetHousesWithinSameDistrict(int-addressId)
{
var addressToMatch=\u addressRepository
.FirstOrDefault(地址=>address.Id==addressId)
返回存储库
.Where(house=>house.Address.District==addressToMatch.District)
}
当我尝试设置addressToMatch变量时,这会导致问题,因为我无法设置District属性,因此我无法编写测试来检查是否返回了正确的匹配地址


我应该如何设置此测试的地址对象?

首先,一个粗略的猜测:可能是将您的
地区
属性声明为
受保护的内部
加上将
程序集:InternalsVisibleTo
属性添加到您的“域”中程序集,以便可以从测试中设置不同的
Distinct

class Address
{
    public virtual string District { get; protected internal set; }
}

或者,您可以向
Address
类添加一个内部构造函数,该构造函数将设置
District
属性的值。同样,用
assembly:InternalsVisibleTo

注释您的“域”程序集。如果您使用的是Moq(问题是用它标记的,所以我假设您是):


也许,
protectedinternal
+
assembly:InternalsVisibleTo
?@DeblatonJean-Philippe相关,但肯定没有重复的IMHO.@DeblatonJean-Philippe一点也不重复。将其设置为
protectedset
并使用setter方法创建子类(作为testfixture的私有类)是一个简单的过程(不是很漂亮,但很实用)解决方法。在没有看到您的测试的情况下,很难给出建议,但是您可以使用需要匹配的地址的模拟,并使用SetupGet返回您想要的值,您可以使用反射设置您需要的值,或者如果您使用MS testing framework,您可以使用PrivateObject设置值。这个答案是所有类型的awesome、 我正要将我的属性设置为InternalsVisibleTo并将其设置为InternalsVisibleTo。或者我打算使用PrivateObject。这个答案很简单也很好。谢谢。除了使用InternalsVisibleTo,还有其他方法吗?这会使我的代码有点混乱和不清晰(我正在练习ddd,所以我的类中所有属性的设置都是私有的),如果您能告诉我一些更优雅的解决方案,我将不胜感激。谢谢
var mockAddress = new Mock<Address>();
mockAddress.SetupGet(p => p.District).Returns("Whatever you want to match");
var mockAddress = new Mock<Address>();
mockAddress.SetupGet(p => p.Id).Returns(42);
mockAddress.SetupGet(p => p.District).Returns("What you want to match");

var mockAddressRepository = new Mock<IRepository<Address>>();
var addresses = new List<Address> { mockAddress.Object };
mockAddressRepository.Setup(p => p.GetEnumerator()).Returns(addresses.GetEnumerator());

var addressToMatch = mockAddressRepository.Object.FirstOrDefault(address => address.Id == 42);
Console.WriteLine(addressToMatch.District);