Moq 没有在继承树中调用正确的方法
Moq does not call correct method in inheritance tree
我有框架源代码,不想修改。但是我需要改变它的行为。我通过为框架代码创建扩展 classes 并按我认为合适的方式修改行为来实现此目的。记住这个背景会让你更好地理解我想要实现的目标。
框架代码:
public interface IItem
{
void PerformAction();
}
public class Item : IItem
{
public IItemChild itemChild;
public Item(IItemChild ic)
{
itemChild = ic;
}
public void PerformAction()
{
itemChild.PerformAction(1, c:1);
}
}
public interface IItemChild
{
void PerformAction(int a = 0, int b = 0, int c = 0);
}
public class ItemChild : IItemChild
{
public virtual void PerformAction(int a = 0, int b = 0, int c = 0)
{
}
}
框架扩展代码:
public interface IItemExtension : IItem
{
}
public class ItemExtension : Item, IItemExtension
{
public ItemExtension(IItemChildExtension ice) : base(ice) { }
}
public interface IItemChildExtension : IItemChild
{
void PerformAction(int a = 0, int b = 0, int c = 0);
}
public class ItemChildExtension : ItemChild, IItemChildExtension
{
public void PerformAction(int a = 0, int b = 0, int c = 0)
{
}
}
我还编写了一个测试 class 来检查扩展代码的行为:
public class Tests
{
[SetUp]
public void Setup()
{
}
[Test]
public void Test1()
{
var itemChildMock = new Mock<IItemChildExtension>();
itemChildMock.Setup(mock => mock.PerformAction(1, 0, 1)).Callback(() =>
{
var test = 2;
});
var itemExtension = new ItemExtension(itemChildMock.Object);
//itemExtension = new ItemExtension(new ItemChildExtension());
itemExtension.PerformAction();
var invocations = itemChildMock.Invocations;
}
}
这段代码中的回调函数没有被触发。在检查模拟调用时,我注意到调用了 IItemChild.PerformAction(1, 0, 1),即使模拟是为 IItemChildExtension 创建的。
取消对 itemExtension 的第二次赋值的注释摆脱了模拟,而是使用 "real" 实现。 运行 这导致 IItemChildExtension.PerformAction(1, 0, 1) 被调用。我希望我的测试执行无需模拟即可执行的相同方法。
为什么 mock 调用了错误的方法?我是否缺少一些会导致所需行为的配置?
IItemChildExtension.PerformAction
隐藏继承自 IItemChild
的成员
显示的设置是在 IItemChildExtension.PerformAction
而不是 IItemChild
上完成的
您必须明确告诉 Moq 您希望调用哪个成员。
//Arrange
var itemChildMock = new Mock<IItemChildExtension>();
itemChildMock.As<IItemChild>().Setup(mock => mock.PerformAction(1, 0, 1)).Callback(() => {
var test = 2;
});
var itemExtension = new ItemExtension(itemChildMock.Object);
//itemExtension = new ItemExtension(new ItemChildExtension());
//Act
itemExtension.PerformAction();
var invocations = itemChildMock.Invocations;
注意设置期望值时使用.As<IItemChild>()
按照预期更改测试练习。
如果我删除隐藏派生成员的成员
public interface IItemChildExtension : IItemChild {
//void PerformAction(int a = 0, int b = 0, int c = 0);
}
测试在运行时表现符合预期,没有最初建议的更改。
我有框架源代码,不想修改。但是我需要改变它的行为。我通过为框架代码创建扩展 classes 并按我认为合适的方式修改行为来实现此目的。记住这个背景会让你更好地理解我想要实现的目标。
框架代码:
public interface IItem
{
void PerformAction();
}
public class Item : IItem
{
public IItemChild itemChild;
public Item(IItemChild ic)
{
itemChild = ic;
}
public void PerformAction()
{
itemChild.PerformAction(1, c:1);
}
}
public interface IItemChild
{
void PerformAction(int a = 0, int b = 0, int c = 0);
}
public class ItemChild : IItemChild
{
public virtual void PerformAction(int a = 0, int b = 0, int c = 0)
{
}
}
框架扩展代码:
public interface IItemExtension : IItem
{
}
public class ItemExtension : Item, IItemExtension
{
public ItemExtension(IItemChildExtension ice) : base(ice) { }
}
public interface IItemChildExtension : IItemChild
{
void PerformAction(int a = 0, int b = 0, int c = 0);
}
public class ItemChildExtension : ItemChild, IItemChildExtension
{
public void PerformAction(int a = 0, int b = 0, int c = 0)
{
}
}
我还编写了一个测试 class 来检查扩展代码的行为:
public class Tests
{
[SetUp]
public void Setup()
{
}
[Test]
public void Test1()
{
var itemChildMock = new Mock<IItemChildExtension>();
itemChildMock.Setup(mock => mock.PerformAction(1, 0, 1)).Callback(() =>
{
var test = 2;
});
var itemExtension = new ItemExtension(itemChildMock.Object);
//itemExtension = new ItemExtension(new ItemChildExtension());
itemExtension.PerformAction();
var invocations = itemChildMock.Invocations;
}
}
这段代码中的回调函数没有被触发。在检查模拟调用时,我注意到调用了 IItemChild.PerformAction(1, 0, 1),即使模拟是为 IItemChildExtension 创建的。
取消对 itemExtension 的第二次赋值的注释摆脱了模拟,而是使用 "real" 实现。 运行 这导致 IItemChildExtension.PerformAction(1, 0, 1) 被调用。我希望我的测试执行无需模拟即可执行的相同方法。
为什么 mock 调用了错误的方法?我是否缺少一些会导致所需行为的配置?
IItemChildExtension.PerformAction
隐藏继承自 IItemChild
显示的设置是在 IItemChildExtension.PerformAction
而不是 IItemChild
您必须明确告诉 Moq 您希望调用哪个成员。
//Arrange
var itemChildMock = new Mock<IItemChildExtension>();
itemChildMock.As<IItemChild>().Setup(mock => mock.PerformAction(1, 0, 1)).Callback(() => {
var test = 2;
});
var itemExtension = new ItemExtension(itemChildMock.Object);
//itemExtension = new ItemExtension(new ItemChildExtension());
//Act
itemExtension.PerformAction();
var invocations = itemChildMock.Invocations;
注意设置期望值时使用.As<IItemChild>()
按照预期更改测试练习。
如果我删除隐藏派生成员的成员
public interface IItemChildExtension : IItemChild {
//void PerformAction(int a = 0, int b = 0, int c = 0);
}
测试在运行时表现符合预期,没有最初建议的更改。