如何模拟嵌套属性和对象及其功能?

时间:2016-04-17 13:30:57

标签: c# unit-testing moq

我有下面的代码我想测试,但我不确定是否可能。

我有EF存储库,它们被组合成一个类作为公共属性。我不确切地知道它是否是错误的解决方案,但是管理代码及其依赖关系更容易。只有可测试性仍然是一个问题。

我的测试目的是通过

注入数据
  

administrationRepository.ModuleScreen.GetAll()

方法并捕获结果。我知道它可以在部署后进行测试,但我希望在构建时间内进行测试,以便尽可能快地获得反馈。

我在这里经历了问题和答案,但我找不到答案。在我的代码中,我达到了设置属性的程度,但是当我调用administrationRepoMock.Object.ModuleScreen.GetAll()时,ReSharper只提供来自Entitiy Framework的方法而不是Moq相关的函数。

我想要的可能吗?如果是这样,怎么样?我的设计适合这个吗?如果没有,你可以给我文章,网址,我可以看到例子吗?

存储库:

public interface IModuleScreen
{
    IEnumerable<DomainModel.Administration.ModuleScreen> GetAll();
}

public interface IAdministrationRepository
{
    IModuleScreen ModuleScreen { get; }
}

public partial class AdministrationRepository : IAdministrationRepository
{
    public virtual IModuleScreen ModuleScreen { get; private set; }

    public AdministrationRepository( IModuleScreen moduleScreen )
    {
        this.ModuleScreen = moduleScreen;
    }
}

应用:

public partial class DigitalLibraryApplication : IDigitalLibraryApplication
{
    private IAdministrationRepository _administrationRepository;
    private IMapper.IMapper.IMapper _mapper;
    private IDiLibApplicationHelper _dilibApplicationHelper;

    #region Ctor
    public DigitalLibraryApplication( IAdministrationRepository administrationRepository, IMapper.IMapper.IMapper mapper, IDiLibApplicationHelper diLibApplicationHelper)
    {
        _administrationRepository = administrationRepository;
        _mapper = mapper;
        _dilibApplicationHelper = diLibApplicationHelper;
    }
    #endregion

    public IEnumerable<ModuleScreenContract> GetModuleScreens()
    {
        //inject data here
        IEnumerable<ModuleScreen> result = _administrationRepository.ModuleScreen.GetAll();

        List<ModuleScreenContract> mappedResult = _mapper.MapModuleScreenToModuleScreenContracts(result);

        return mappedResult;
    }

}

测试代码:

[Test]
public void ItCalls_ModuleRepository_Get_Method()
{
    List<SayusiAndo.DiLib.DomainModel.Administration.ModuleScreen> queryResult = new List<SayusiAndo.DiLib.DomainModel.Administration.ModuleScreen>()
    {
        new DomainModel.Administration.ModuleScreen()
        {
            Id = 100,
        },
    };

    var moduleScreenMock = new Mock<IModuleScreen>();
    moduleScreenMock.Setup(c => c.GetAll()).Returns(queryResult);

    administrationRepoMock.SetupProperty(c => c.ModuleScreen, moduleScreenMock.Object);


    var mapperMock = new Mock<IMapper.IMapper.IMapper>();
    var dilibApplicationHerlperMock = new Mock<IDiLibApplicationHelper>();


    IDigitalLibraryApplication app = new DigitalLibraryApplication( administrationRepoMock.Object, mapperMock.Object, dilibApplicationHerlperMock.Object );

    app.GetModules();
    //issue is here
    administrationRepoMock.Object.ModuleScreen.GetAll() //???
}

1 个答案:

答案 0 :(得分:3)

以下是运行时经过的测试的重构。您可以更新通过标准以适合您对成功测试的定义。

[Test]
public void ItCalls_ModuleRepository_Get_Method() {
    // Arrange
    List<ModuleScreen> queryResult = new List<ModuleScreen>()
    {
        new ModuleScreen()
        {
            Id = 100,
        },
    };
    //Building mapped result from query to compare results later
    List<ModuleScreenContract> expectedMappedResult = queryResult
        .Select(m => new ModuleScreenContract { Id = m.Id })
        .ToList();

    var moduleScreenMock = new Mock<IModuleScreen>();
    moduleScreenMock
        .Setup(c => c.GetAll())
        .Returns(queryResult)
        .Verifiable();

    var administrationRepoMock = new Mock<IAdministrationRepository>();
    administrationRepoMock
        .Setup(c => c.ModuleScreen)
        .Returns(moduleScreenMock.Object)
        .Verifiable();

    var mapperMock = new Mock<IMapper>();
    mapperMock.Setup(c => c.MapModuleScreenToModuleScreenContracts(queryResult))
        .Returns(expectedMappedResult)
        .Verifiable();

    //NOTE: Not seeing this guy doing anything. What's its purpose
    var dilibApplicationHerlperMock = new Mock<IDiLibApplicationHelper>();

    IDigitalLibraryApplication app = new DigitalLibraryApplication(administrationRepoMock.Object, mapperMock.Object, dilibApplicationHerlperMock.Object);

    //Act (Call the method under test)
    var actualMappedResult = app.GetModuleScreens();

    //Assert
    //Verify that configured methods were actually called. If not, test will fail.
    moduleScreenMock.Verify();
    mapperMock.Verify();
    administrationRepoMock.Verify();

    //there should actually be a result.
    Assert.IsNotNull(actualMappedResult);
    //with items
    CollectionAssert.AllItemsAreNotNull(actualMappedResult.ToList());
    //There lengths should be equal
    Assert.AreEqual(queryResult.Count, actualMappedResult.Count());
    //And there should be a mapped object with the same id (Assumption)
    var expected = queryResult.First().Id;
    var actual = actualMappedResult.First().Id;
    Assert.AreEqual(expected, actual);
}