反思单元测试中的模拟数据(Rhino)
Reflection on mocked data in unit tests (Rhino)
我有一些使用反射选择 属性 的代码。它工作正常,但我无法对其进行单元测试。显然,它创建的模拟没有任何属性。
谁能告诉我如何使用反射从 Mocked 对象中获取 属性? (或者解释为什么不可能?)
var target = To.GetType().GetProperties()
.Single(x => typeof(IRepository<T>).IsAssignableFrom(x.PropertyType))
.GetValue(To) as IRepository<T>;
我将其用于副本 class,它允许复制任何实体类型的数据,并期望包含 IRepository 的 UnitOfWork,其中 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 );
我发现了问题:
这些属性可作为显式属性使用。
要访问这些类型的属性,您需要接口映射。
这意味着我应该改变这个:
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 实现使用了 'implicit' 属性,所以这解释了为什么它起作用而单元测试失败。此外,使用地图通常更好(/更正确)(-> 如果我用显式道具进行接口的另一个实现,就没有机会出现问题)。所以我想这是一个很好的单元测试:)
此致
我有一些使用反射选择 属性 的代码。它工作正常,但我无法对其进行单元测试。显然,它创建的模拟没有任何属性。 谁能告诉我如何使用反射从 Mocked 对象中获取 属性? (或者解释为什么不可能?)
var target = To.GetType().GetProperties()
.Single(x => typeof(IRepository<T>).IsAssignableFrom(x.PropertyType))
.GetValue(To) as IRepository<T>;
我将其用于副本 class,它允许复制任何实体类型的数据,并期望包含 IRepository 的 UnitOfWork,其中 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 );
我发现了问题: 这些属性可作为显式属性使用。 要访问这些类型的属性,您需要接口映射。
这意味着我应该改变这个:
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 实现使用了 'implicit' 属性,所以这解释了为什么它起作用而单元测试失败。此外,使用地图通常更好(/更正确)(-> 如果我用显式道具进行接口的另一个实现,就没有机会出现问题)。所以我想这是一个很好的单元测试:)
此致