【问题标题】:Reflection on mocked data in unit tests (Rhino)对单元测试中模拟数据的反思(Rhino)
【发布时间】:2015-07-23 09:39:51
【问题描述】:

我有一些使用反射选择属性的代码。它工作正常,但我无法对其进行单元测试。显然,它创建的模拟没有任何属性。 谁能告诉我如何使用反射从模拟对象中获取属性? (或者解释一下为什么不可能?)

var target = To.GetType().GetProperties()
    .Single(x => typeof(IRepository<T>).IsAssignableFrom(x.PropertyType))
    .GetValue(To) as IRepository<T>;

我将此用于复制类,它允许复制任何实体类型的数据,并期望 UnitOfWork 包含一个 IRepository,其中 T 是您要复制的类型。

public class TableCopier<T> : ICopier where T : EntityBase
{
    public IUnitOfWork From { get; set; }
    public IUnitOfWork To { get; set; }

    public virtual int Copy(IProgressReporter progres = null)
    {
        lock (this)
        {
            var target = To.GetType().GetProperties()
                .Single(x => typeof(IRepository<T>).IsAssignableFrom(x.PropertyType))
                .GetValue(To) as IRepository<T>;
            //...
        }
    }
}

工作单元如下所示:

public interface IUnitOfWork
{
    IRepository<Parameter> ParameterRepository { get; }
    IRepository<Company> CompanyRepository { get; }
    IRepository<CompanyAccountancynumber> CompanyAccountancynumberRepository { get; }
    //...

最后是单元测试:

    [Test]
    public void DefaultCopy()
    {
        // (removed some code)
        var to = MockRepository.GenerateStrictMock<IUnitOfWork>();

        var target = MockRepository.GenerateStrictMock<IRepository<CompanyDataset>>();
        to.Stub(x => x.CompanyDatasetRepository).Return(target);
        var inserted = new List<CompanyDataset>();
        target.Stub(x => x.BulkInsert(null))
            .IgnoreArguments()
            .WhenCalled(x => inserted.AddRange(x.Arguments[0] as IEnumerable<CompanyDataset>));

        //ACT
        var copier = new TableCopier<CompanyDataset>() as ICopier;
        copier.Copy(from, to, map, log, null, CancellationToken.None );

【问题讨论】:

    标签: c# unit-testing reflection mocking rhino-mocks


    【解决方案1】:

    我发现了问题: 这些属性可作为显式属性使用。 要访问这些类型的属性,您需要接口映射。

    这意味着我应该改变这个:

    var target = To.GetType().GetProperties()
        .Single(x => typeof(IRepository<T>).IsAssignableFrom(x.PropertyType))
        .GetValue(To) as IRepository<T>;
    

    到这里:

    var target = To.GetType().GetInterfaceMap(typeof(IUnitOfWork))
        .InterfaceMethods
        .Single(x => (typeof(IRepository<T>).IsAssignableFrom(x.ReturnType)))
        .Invoke(To, null) as IRepository<T>;
    

    我自己的 IUnitOfWork 实现使用了“隐式”属性,这就解释了为什么它有效并且单元测试失败了。同样使用地图通常会更好(/更正确)(->如果我要使用显式道具制作接口的另一个实现,就没有机会出现问题)。所以我想这是一个很好的单元测试:)

    问候

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-13
      • 1970-01-01
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多