我正在尝试使用moq模拟第三方库的方法。 问题是我正在模拟的方法返回一个在这个框架内部的对象,因此我无法实现这一点。
在下面的示例中,ChangeCollection和ItemChange都是内部的,我得到错误:'无法访问内部构造函数'ChangeCollection'here'
我遇到问题找出一个好的解决方案,有人有任何想法吗?
[TestMethod]
public void GetItemsForExistingEMails_should_call_GetItems_atleast_once()
{
ewsMock = new Mock<IEwsIntegration>();
ewsMock.Setup(e => e.GetItems()).Returns(new ChangeCollection<ItemChange>);
var emailService = new EmailService(ewsMock.Object);
var items = emailService.GetItemsForExistingEMails();
ewsMock.Verify(e => e.GetItems(), Times.AtLeast(1));
Assert.AreEqual(0, items.Count());
}
public interface IEwsIntegration
{
ChangeCollection<ItemChange> GetItems();
}
答案 0 :(得分:0)
这里有几种可能的选择。
第一个要求您有权访问第三方来源以设置InternalsVisibleTo
。
然后,这允许您访问您引用的dll上的内部成员,并在AssemblyInfo.cs中看起来像这样:
[assembly: InternalsVisibleTo("Mynamespace.MyProject.Tests, PublicKey=00240...")]
其次,因为IEwsIntegration
是公开来自第三方应用程序的类型,您可以更改它,以便返回自己的类型。这将为您提供第三方应用程序的更好抽象。
在这里,我使用AutoMapper来管理第三方应用程序的返回类型和我自己的类型之间的映射。然后你可以模拟出这个依赖项(我使用IAutoMapperWrapper)并让它在测试中返回你的返回类型的具体含义。
即使你使用自己的自定义转换器,你也可以模拟它返回的内容,并提供你自己类型的一些对象。
答案 1 :(得分:0)
我认为您可以在界面中返回IEnumerable<ChangeItem>
。似乎ChangeCollection只是IEnumerable<T>
的实现。
public interface IEwsIntegration
{
IEnumerable<ItemChange> GetItems();
}
然后您只需在设置中返回一个列表
即可ewsMock.Setup(e => e.GetItems()).Returns(new List<ItemChange>());
<强>更新强>
由于必须使用仅在具体类上定义的属性,因此必须创建适配器。
首先使用具体类中的成员创建一个接口。
public interface IChangeCollection<T> : IEnumerable<T>
{
bool MoreChangesAvailable { get; }
string SyncState { get; }
}
确保从界面返回此类型:
public interface IEwsIntegration
{
IChangeCollection<ItemChange> GetItems();
}
然后你必须创建一个IChangeCollection<T>
的实现,它只是直接调用ChangeCollection的实例。
public class ChangeCollectionAdapter<T> : IChangeCollection<T>
{
private readonly ChangeCollection _changeCollection;
public ChangeCollectionAdapter(ChangeCollection changeCollection)
{
_changeCollection = changeCollection;
}
public bool MoreChangesAvailable
{
get { return _changeCollection.MoreChangesAvailable; }
}
//other members
}