C# 如何在Moq中设置重载方法调用?
我试图模拟映射接口C# 如何在Moq中设置重载方法调用?,c#,moq,overloading,C#,Moq,Overloading,我试图模拟映射接口IMapper: public interface IMapper<TFoo, TBar> { TBar Map(TFoo foo); TFoo Map(TBar bar); } 但是,当进行第二次Map调用时,映射器模拟会抛出,因为它只需要一次调用 在运行时的设置过程中观察映射器模拟,我可以查看映射(TFoo foo)重载的注册情况,然后在设置映射(TBar bar)重载时看到它被替换 这是Moq处理设置的方式的问题,还是在这种情况下需要使用不同
IMapper
:
public interface IMapper<TFoo, TBar> {
TBar Map(TFoo foo);
TFoo Map(TBar bar);
}
但是,当进行第二次Map
调用时,映射器模拟会抛出,因为它只需要一次调用
在运行时的设置过程中观察映射器模拟,我可以查看映射(TFoo foo)
重载的注册情况,然后在设置映射(TBar bar)
重载时看到它被替换
这是Moq处理设置的方式的问题,还是在这种情况下需要使用不同的语法
编辑
以下是来自测试构造函数的实际实例化代码:
public class TestClass {
private readonly MockRepository _repository = new MockRepository(MockBehavior.Strict);
public TestClass() {
//...
_mapperMock = _repository.Create
<IMapper<RequestData.Foo, ResponseData.Bar>>();
//...
}
}
公共类TestClass{
私有只读MockRepository _repository=新MockRepository(MockBehavior.Strict);
公共测试类(){
//...
_mapperMock=\u repository.Create
();
//...
}
}
编辑2
下面是一个完整的失败测试用例:
public interface IMapper<TFoo, TBar> {
TFoo Map(TBar bar);
TBar Map(TFoo foo);
}
public class Foo {
public override int GetHashCode() {
// return base.GetHashCode();
return 1;
}
}
public class Bar {
public override int GetHashCode() {
// return base.GetHashCode();
return 2;
}
}
[Test]
public void TestIt()
{
// Arrange
var _mapperMock = new Mock<IMapper<Foo, Bar>>(MockBehavior.Strict);
var fooMock = new Mock<Foo>();
var barMock = new Mock<Bar>();
_mapperMock.Setup(m => m.Map(fooMock.Object)).Returns(barMock.Object);
_mapperMock.Setup(m => m.Map(barMock.Object)).Returns(fooMock.Object);
// Act - breaks on first line below this comment
var bar = _mapperMock.Object.Map(fooMock.Object);
var foo = _mapperMock.Object.Map(barMock.Object);
// Assert
_mapperMock.Verify(x => x.Map(fooMock.Object), Times.Once());
_mapperMock.Verify(x => x.Map(barMock.Object), Times.Once());
}
公共接口IMapper{
TFoo图(TBar条);
TBar地图(TFoo-foo);
}
公开课Foo{
公共覆盖int GetHashCode(){
//返回base.GetHashCode();
返回1;
}
}
公共类酒吧{
公共覆盖int GetHashCode(){
//返回base.GetHashCode();
返回2;
}
}
[测试]
公开无效测试()
{
//安排
var\u mapperMock=新模拟(MockBehavior.Strict);
var fooMock=new Mock();
var barMock=new Mock();
_Setup(m=>m.Map(fooMock.Object)).Returns(barMock.Object);
_Setup(m=>m.Map(barMock.Object)).Returns(fooMock.Object);
//Act-在该评论下面的第一行中断
var bar=\u mapperMock.Object.Map(fooMock.Object);
var foo=_mapperMock.Object.Map(barMock.Object);
//断言
_Verify(x=>x.Map(fooMock.Object),Times.Once());
_Verify(x=>x.Map(barMock.Object),Times.Once());
}
如果我在Foo
或Bar
上注释掉GetHashCode()
覆盖,或者在两者上注释掉GetHashCode()
覆盖,则测试用例通过。或者,如果我没有使用Foo
和Bar
的Mock
s,测试用例通过
编辑3
我用更详细的测试用例来解决这个问题。不确定您的
Foo
和Bar
类是什么样子的,但我通过了这个测试(Moq 4.0.10827.0,这是NuGet中最新的一个)
使用Moq;
使用NUnit.Framework;
命名空间控制台应用程序1
{
[测试夹具]
公开课考试
{
[测试]
公开无效测试()
{
//安排
var_mapperMock=new Mock();
var fooMock=new Mock();
var barMock=new Mock();
_Setup(m=>m.Map(fooMock.Object)).Returns(barMock.Object);
_Setup(m=>m.Map(barMock.Object)).Returns(fooMock.Object);
//表演
var bar=\u mapperMock.Object.Map(fooMock.Object);
var foo=_mapperMock.Object.Map(barMock.Object);
//断言
arame(bar,barMock.Object);
areseme(foo,fooMock.Object);
_Verify(x=>x.Map(fooMock.Object),Times.Once());
_Verify(x=>x.Map(barMock.Object),Times.Once());
}
}
公共类酒吧
{
}
公开课Foo
{
}
}
能否在实例化mapperMock的地方包含您的代码?谢谢。我唯一能看到你上面的代码失败的时候是如果泛型TFoo和TBar是相同的类型。例如,var_mapperMock=new Mock();如果它们是不同的(例如var _mapperMock=new Mock();),那么它们应该是不同的类型,继承自不同的子类型。当我在调试器中单步执行测试时,我可以看到方法分辨率正确变化,但是在进行第二次Setup
调用时,第一次调用被第二次调用所取代。我还将添加实际的实例化代码。模拟的默认行为是Loose
。如果\u mapperMock
使用Strict
行为,上述测试是否仍然通过?我使用var\u mapperMock=new Mock(MockBehavior.Strict)测试了上述测试代码>并且它仍然通过。有趣的是…我想知道它是否与使用MockRepository
定义映射器有关。我将尝试直接实例化\u mapperMock
,看看这是否有区别。在我的案例中,仍然使用来自网站的DLL(否则我们使用的是从源AFAICT构建的副本),并使用本地实例化的映射器模拟。但是,我发现它与Foo
和Bar
下面的基类有关-如果我在没有指定基类的情况下运行测试,它将通过,但是如果我指定Foo
和Bar
扩展各自的基类,测试失败。你是否发布了Foo
和Bar
的代码以及导致测试失败的基本类型?
public interface IMapper<TFoo, TBar> {
TFoo Map(TBar bar);
TBar Map(TFoo foo);
}
public class Foo {
public override int GetHashCode() {
// return base.GetHashCode();
return 1;
}
}
public class Bar {
public override int GetHashCode() {
// return base.GetHashCode();
return 2;
}
}
[Test]
public void TestIt()
{
// Arrange
var _mapperMock = new Mock<IMapper<Foo, Bar>>(MockBehavior.Strict);
var fooMock = new Mock<Foo>();
var barMock = new Mock<Bar>();
_mapperMock.Setup(m => m.Map(fooMock.Object)).Returns(barMock.Object);
_mapperMock.Setup(m => m.Map(barMock.Object)).Returns(fooMock.Object);
// Act - breaks on first line below this comment
var bar = _mapperMock.Object.Map(fooMock.Object);
var foo = _mapperMock.Object.Map(barMock.Object);
// Assert
_mapperMock.Verify(x => x.Map(fooMock.Object), Times.Once());
_mapperMock.Verify(x => x.Map(barMock.Object), Times.Once());
}
using Moq;
using NUnit.Framework;
namespace ConsoleApplication1
{
[TestFixture]
public class Tests
{
[Test]
public void TestIt()
{
// Arrange
var _mapperMock = new Mock<IMapper<Foo, Bar>>();
var fooMock = new Mock<Foo>();
var barMock = new Mock<Bar>();
_mapperMock.Setup(m => m.Map(fooMock.Object)).Returns(barMock.Object);
_mapperMock.Setup(m => m.Map(barMock.Object)).Returns(fooMock.Object);
// Act
var bar = _mapperMock.Object.Map(fooMock.Object);
var foo = _mapperMock.Object.Map(barMock.Object);
// Assert
Assert.AreSame(bar, barMock.Object);
Assert.AreSame(foo, fooMock.Object);
_mapperMock.Verify(x => x.Map(fooMock.Object), Times.Once());
_mapperMock.Verify(x => x.Map(barMock.Object), Times.Once());
}
}
public class Bar
{
}
public class Foo
{
}
}