C# 方法isn';最小起订量中的t

C# 方法isn';最小起订量中的t,c#,unit-testing,moq,C#,Unit Testing,Moq,我很难理解为什么一个方法不能被调用。 我创建了一个小测试代码来重现这个问题 public interface ILoader { IEnumerable<string> LoadAll(); string LoadItem(int key); } public interface IStore { IQueryable<string> Items { get; } } public abstract class StoreBase : ISt

我很难理解为什么一个方法不能被调用。 我创建了一个小测试代码来重现这个问题

public interface ILoader
{
    IEnumerable<string> LoadAll();

    string LoadItem(int key);
}

public interface IStore
{
    IQueryable<string> Items { get; }
}

public abstract class StoreBase : IStore
{
    public void Load()
    {
        Items = LoadItems().ToArray().AsQueryable();
    }

    protected abstract IEnumerable<string> LoadItems();

    public IQueryable<string> Items { get; private set; }
}

public abstract class StoreBase2 : StoreBase
{
    private readonly ILoader _loader;

    protected StoreBase2(ILoader loader)
    {
        _loader = loader;
    }

    protected override IEnumerable<string> LoadItems()
    {
        return _loader.LoadAll();
    }
}
公共接口ILoader
{
IEnumerable LoadAll();
字符串加载项(int键);
}
公共接口晶体管
{
IQueryable项{get;}
}
公共抽象类库:IStore
{
公共空荷载()
{
Items=LoadItems().ToArray().AsQueryable();
}
受保护的抽象IEnumerable LoadItems();
公共IQueryable项{get;private set;}
}
公共抽象类StoreBase 2:StoreBase
{
专用只读ILoader\u加载程序;
受保护的StoreBase2(ILoader加载程序)
{
_装载机=装载机;
}
受保护的覆盖IEnumerable LoadItems()
{
返回_loader.LoadAll();
}
}
这里是测试的主体

Mock<ILoader> mockLoader = new Mock<ILoader>();
mockLoader.Setup(p => p.LoadAll()).Returns(() => Enumerable.Range(1, 10).Select(i => string.Format("Item: {0}", i)));
mockLoader.Setup(p => p.LoadItem(It.IsAny<int>())).Returns((int i) => string.Format("Item: {0}", i));

Mock<StoreBase2> mockStore = new Mock<StoreBase2>(mockLoader.Object);
mockStore.Object.Load();

mockLoader.Verify(p => p.LoadAll());
Mock mockLoader=new Mock();
mockLoader.Setup(p=>p.LoadAll())。返回(()=>Enumerable.Range(1,10)。选择(i=>string.Format(“项:{0}”,i));
Setup(p=>p.LoadItem(It.IsAny())。返回((inti)=>string.Format(“Item:{0}”,i));
Mock mockStore=新的Mock(mockLoader.Object);
mockStore.Object.Load();
验证(p=>p.LoadAll());
如果我引入StoreBase2的具体实现(很抱歉命名),并使用它而不是模拟基类,那么它就可以工作了

public class StoreBaseImpl : StoreBase2
{
    public StoreBaseImpl(ILoader loader) : base(loader) {}
}

void MyTest() 
{
    Mock<ILoader> mockLoader = new Mock<ILoader>();
    mockLoader.Setup(p => p.LoadAll()).Returns(() => Enumerable.Range(1, 10).Select(i => string.Format("Item: {0}", i)));
    mockLoader.Setup(p => p.LoadItem(It.IsAny<int>())).Returns((int i) => string.Format("Item: {0}", i));

    var store = new StoreBaseImpl(mockLoader.Object);
    store.Load();
    mockLoader.Verify(p => p.LoadAll());
}   
公共类StoreBaseImpl:StoreBase2
{
public StoreBaseImpl(ILoader装入器):基本(装入器){}
}
void MyTest()
{
Mock mockLoader=new Mock();
mockLoader.Setup(p=>p.LoadAll())。返回(()=>Enumerable.Range(1,10)。选择(i=>string.Format(“项:{0}”,i));
Setup(p=>p.LoadItem(It.IsAny())。返回((inti)=>string.Format(“Item:{0}”,i));
var store=newstorebaseimpl(mockLoader.Object);
store.Load();
验证(p=>p.LoadAll());
}   
我错过什么了吗


编辑:添加到粘贴箱以便于访问代码:

您没有设置模拟加载(..)方法。

我认为您必须使您的.Setups()可验证,如下所示:

mockLoader.Setup(p => p.LoadAll()).Returns("Blah").Verifiable();
mockLoader.Setup(p => p.LoadItem(It.IsAny<int>())).Returns("Blah").Verifiable();
mockLoader.Setup(p=>p.LoadAll())。返回(“Blah”).Verifiable();
mockLoader.Setup(p=>p.LoadItem(It.IsAny())。返回(“Blah”).Verifiable();

为商店模拟打开对基类的调用:

var mockStore = new Mock<StoreBase2>(mockLoader.Object) { CallBase = true };
var mockStore=newmock(mockLoader.Object){CallBase=true};

此选项定义如果未设置成员的期望值,是否调用基本成员虚拟实现。因此,您无法设置受保护成员的期望值,只有启用此选项才能调用
StoreBase2
LoadItems()
方法。否则将不执行
\u loader.LoadAll()

为什么要设置它?它的基类提供的实现对我来说很好。顺便说一句,它不是“可设置的”,因为它不是虚拟的。如果您将mockLoader的行为设置为strict怎么办:Mock mockLoader=new Mock(MockBehavior.strict);这就成功了!:)无论如何,我对mockLoader设定了期望,这对我来说已经足够了。