2017-11-10 16 views
2

테스트 할 추상 클래스가 있습니다. 이 클래스에는 상속 된 클래스에서 정의하는 DAO에 대한 추상 속성이 있습니다.AutoFixture AutoMoq에서 속성을 사용하지 않습니다.

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); 
    } 
} 

은 내가 DeviceGroupDao라는 속성을 조롱하기 위해 노력하고있어 그래서 Updatedeviceindexes 방법을 테스트하려는.

[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; 

    [TestFixtureSetUp] 
    public void Init() 
    { 
     fixture = new Fixture().Customize(new AutoMoqCustomization()); 
     deviceGroupDaoMock = fixture.Freeze<Mock<IDeviceGroupDao<DeviceGroup>>>(); 
     subject = fixture.Freeze<Mock<DeviceGroupManagerBase<DeviceGroup>>>(); 
    } 

    [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); 
     // The resultDeviceGroup will not be contain a previously defined object 

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

나는이 방법으로 내 장치 개체에 대한 등록을 추가하려고 :

fixture.Register(() => deviceGroup); 

하지만 난 여전히 새로운 객체를 얻고있다.

어떻게하면 IDeviceGroupDao<TDeviceGroup>을 모의 할 수 있습니까?

답변

2

DeviceGroupManagerBase은 추상적 인 기본 클래스이므로 SUT Double이 필요합니다.

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); 
    } 
} 

그렇지 않으면, 당신은 정의하고있다 최우선 protected 회원을위한 MOQ의 API를 사용해야하지만 더 많은 일 : 당신이 DeviceGroupDao 재산 public을 할 경우는 어떻게하는 것이 가장 쉬운 방법이다.

그럼 당신은 subjectDeviceGroupDao 속성을 재정의해야합니다 :

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); 
    } 
} 

이 지금 내 컴퓨터에 전달합니다.

2

DeviceGroupDao이 보호되어 있으므로 외부에서 액세스 할 수있는 방법을 찾아야합니다. 값을 설정할 수있는 스텁을 만듭니다.

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; 
     } 
    } 
} 

그런 다음 IDeviceGroupDao<TDeviceGroup>을 조롱하여 테스트를 위해 스텁에 삽입 할 수 있습니다.

+1

이 답변은 디자인이 완전히 잠겨있는 경우에 유용합니다. 테스트에서는 유형을 안전하게 유지하면서 '보호 된'속성의 문제를 훌륭하게 해결합니다. 그것은 또한 Constructor Injection이 전반적으로 더 좋은 디자인이 될 것이라는 것을 보여줍니다. 그래서 스스로를 중복시키는 것이 이것의 또 다른 이점입니다. –