C# AutoFixture AutoMoq不将我的模拟用于属性

C# AutoFixture AutoMoq不将我的模拟用于属性,c#,unit-testing,nunit,moq,autofixture,C#,Unit Testing,Nunit,Moq,Autofixture,我有一个要测试的抽象类。我的DAO在这个类中有一个抽象属性,我在继承的类中定义了这个属性 public abstract class DeviceGroupManagerBase<TDeviceGroup> where TDeviceGroup : DeviceGroup { protected abstract IDeviceGroupDao<TDeviceGroup> DeviceGroupDao { get; } public TDeviceGr

我有一个要测试的抽象类。我的DAO在这个类中有一个抽象属性,我在继承的类中定义了这个属性

public abstract class DeviceGroupManagerBase<TDeviceGroup> where TDeviceGroup : DeviceGroup 
{
    protected abstract IDeviceGroupDao<TDeviceGroup> DeviceGroupDao { get; }

    public TDeviceGroup UpdateDeviceIndexes(Device device)
    {
        return DeviceGroupDao.GetDeviceGroup(device.Group.Id);
    }
}
我还尝试通过以下方式为我的设备对象添加注册:

fixture.Register(() => deviceGroup);
但我还是得到了一个新的东西


如何模拟
IDeviceGroupDao

因为
设备组dao
受到保护,您需要找到从外部访问它的方法。创建允许您设置其值的存根

public class DeviceGroupManagerBaseStub<TDeviceGroup> 
    : DeviceGroupManagerBase<TDeviceGroup> where TDeviceGroup : DeviceGroup {

    private IDeviceGroupDao<TDeviceGroup> deviceGroupDao;

    public DeviceGroupManagerBaseStub(IDeviceGroupDao<TDeviceGroup> deviceGroupDao) {
        this.deviceGroupDao = deviceGroupDao;
    }

    protected override IDeviceGroupDao<TDeviceGroup> DeviceGroupDao {
        get {
            return deviceGroupDao;
        }
    }
}
公共类设备组管理器数据库
:DeviceGroupManager数据库,其中TDeviceGroup:DeviceGroup{
私有IDE组设备组DAO;
公用设备组管理器数据库(IDeviceGroupDao设备组DAO){
this.deviceGroupDao=deviceGroupDao;
}
受保护的重写IDeviceGroupDao设备GroupDAO{
得到{
返回设备组DAO;
}
}
}

然后,您可以模拟
IDeviceGroupDao
并将其注入存根中进行测试。

由于
DeviceGroupManagerBase
是一个抽象基类,因此您需要一个。如果将
DeviceGroupDao
属性
设置为公共
,则最容易做到:

public abstract class DeviceGroupManagerBase<TDeviceGroup> where TDeviceGroup : DeviceGroup
{
    public abstract IDeviceGroupDao<TDeviceGroup> DeviceGroupDao { get; }

    public TDeviceGroup UpdateDeviceIndexes(Device device)
    {
        return DeviceGroupDao.GetDeviceGroup(device.Group.Id);
    }
}
以下是完整的测试:

[TestFixture]
[Category("Unit")]
public class DeviceGroupManagerBaseTests
{
    private IFixture fixture;
    private Mock<DeviceGroupManagerBase<DeviceGroup>> subject;
    private Mock<IDeviceGroupDao<DeviceGroup>> deviceGroupDaoMock;
    private DeviceGroupManagerBase<DeviceGroup> Manager => subject.Object;

    [OneTimeSetUp]
    public void Init()
    {
        fixture = new Fixture().Customize(new AutoMoqCustomization());
        deviceGroupDaoMock = fixture.Freeze<Mock<IDeviceGroupDao<DeviceGroup>>>();
        subject = fixture.Freeze<Mock<DeviceGroupManagerBase<DeviceGroup>>>();
        subject.SetupGet(x => x.DeviceGroupDao).Returns(deviceGroupDaoMock.Object);
    }

    [Test]
    public void TestUpdateDeviceIndexes()
    {
        var device = fixture.Create<Device>();
        var deviceGroup = fixture.Create<DeviceGroup>();

        deviceGroupDaoMock.Setup(x => x.GetDeviceGroup(It.IsAny<int>())).Returns(deviceGroup);

        var result = Manager.UpdateDeviceIndexes(device);

        Assert.AreEqual(deviceGroup.Id, result.Id);
    }
}
[TestFixture]
[类别(“单位”)]
公共类设备组管理器集测试
{
专用IFixture固定装置;
私人模拟主体;
私有模拟设备groupdaomock;
私有设备GroupManagerBase Manager=>subject.Object;
[一次性设置]
公共void Init()
{
夹具=新夹具()。自定义(新的AutoMoqCustomization());
deviceGroupDaoMock=fixture.Freeze();
主题=fixture.Freeze();
subject.SetupGet(x=>x.DeviceGroupDao).Returns(deviceGroupDaoMock.Object);
}
[测试]
public void TestUpdateDeviceIndexes()
{
var device=fixture.Create();
var deviceGroup=fixture.Create();
deviceGroupDaoMock.Setup(x=>x.GetDeviceGroup(It.IsAny())。返回(deviceGroup);
var result=Manager.updatedeviceindex(设备);
AreEqual(deviceGroup.Id,result.Id);
}
}

这个问题现在会传到我的机器上。

如果设计完全锁定,这个答案很有用。它很好地解决了属性受保护的问题,同时保持测试的类型安全。我认为,这也证明了构造函数注入总体上是一种更好的设计,因此使其自身冗余是另一个好处:)
subject.SetupGet(x => x.DeviceGroupDao).Returns(deviceGroupDaoMock.Object);
[TestFixture]
[Category("Unit")]
public class DeviceGroupManagerBaseTests
{
    private IFixture fixture;
    private Mock<DeviceGroupManagerBase<DeviceGroup>> subject;
    private Mock<IDeviceGroupDao<DeviceGroup>> deviceGroupDaoMock;
    private DeviceGroupManagerBase<DeviceGroup> Manager => subject.Object;

    [OneTimeSetUp]
    public void Init()
    {
        fixture = new Fixture().Customize(new AutoMoqCustomization());
        deviceGroupDaoMock = fixture.Freeze<Mock<IDeviceGroupDao<DeviceGroup>>>();
        subject = fixture.Freeze<Mock<DeviceGroupManagerBase<DeviceGroup>>>();
        subject.SetupGet(x => x.DeviceGroupDao).Returns(deviceGroupDaoMock.Object);
    }

    [Test]
    public void TestUpdateDeviceIndexes()
    {
        var device = fixture.Create<Device>();
        var deviceGroup = fixture.Create<DeviceGroup>();

        deviceGroupDaoMock.Setup(x => x.GetDeviceGroup(It.IsAny<int>())).Returns(deviceGroup);

        var result = Manager.UpdateDeviceIndexes(device);

        Assert.AreEqual(deviceGroup.Id, result.Id);
    }
}