【问题标题】:Moq a function with anonymous typeMoq 具有匿名类型的函数
【发布时间】:2016-09-09 17:07:41
【问题描述】:

我正在尝试模拟这个方法

Task<TResult> GetResultAsync<TResult>(Func<string, TResult> transformFunc)

喜欢这个

iMock.Setup(m => m.GetResultAsync(It.IsAny<Func<string, object>>())).ReturnsAsync(new { isPair = false });

测试执行调用的方法将匿名类型传递给这样的泛型参数

instance.GetResultAsync(u => new {isPair = u == "something" }) //dont look at the function return because as generic could have diferent implementations in many case

Moq 永远不会将我的 GetResultAsync 方法与发送的参数匹配。

我正在使用最小起订量 4

【问题讨论】:

  • 不确定...但为此目的使用安装程序可能不正确。如果您在单元测试var testObject = { whatevs } 中创建了匿名对象,您可以跳过设置并在最后iMock.Verify(x =&gt; x.GetResultAsync(testObject)) 进行验证。我相信这应该会按预期工作。
  • 您希望模拟的行为如何?你没有指定任何东西。
  • Will 和 Yacoub 感谢您的关注。我用这个模拟方法的返回更新了我的问题。 @Will,我需要模拟该方法的行为,因为它将在我正在测试的另一个方法中使用
  • 提醒一下,如果不付出额外的努力,这将无法正常工作。您不能创建匿名对象,并在另一个项目中使用它。我遇到了an issue doing the same thing last year
  • 我将此作为问题发布在 Moq 的问题跟踪器上:moq/moq4#552。匹配匿名类型的对象看起来应该起作用;我会调查的。

标签: c# unit-testing moq anonymous-function anonymous-types


【解决方案1】:

匿名类型会给你带来麻烦。你需要一个具体的类型才能工作。

以下示例在我更改时有效

instance.GetResultAsync(u => new {isPair = u == "something" })

instance.GetResultAsync(u => (object) new {isPair = u == "something" })

Moq 无法匹配匿名类型,这就是为什么您在调用时会收到 null

[TestClass]
public class MoqUnitTest {
    [TestMethod]
    public async Task Moq_Function_With_Anonymous_Type() {
        //Arrange
        var expected = new { isPair = false };

        var iMock = new Mock<IService>();
        iMock.Setup(m => m.GetResultAsync(It.IsAny<Func<string, object>>()))
            .ReturnsAsync(expected);

        var consumer = new Consumer(iMock.Object);

        //Act   
        var actual = await consumer.Act();

        //Assert
        Assert.AreEqual(expected, actual);
    }

    public interface IService {
        Task<TResult> GetResultAsync<TResult>(Func<string, TResult> transformFunc);
    }

    public class Consumer {
        private IService instance;

        public Consumer(IService service) {
            this.instance = service;
        }

        public async Task<object> Act() {
            var result = await instance.GetResultAsync(u => (object)new { isPair = u == "something" });
            return result;
        }
    }
}

如果调用GetResultAsync 的代码依赖于使用匿名类型,那么您尝试对测试执行的操作将不适用于您当前的设置。您可能需要为该方法提供具体类型。

[TestClass]
public class MoqUnitTest {

    [TestMethod]
    public async Task Moq_Function_With_Concrete_Type() {
        //Arrange
        var expected = new ConcreteType { isPair = false };

        var iMock = new Mock<IService>();
        iMock.Setup(m => m.GetResultAsync(It.IsAny<Func<string, ConcreteType>>()))
            .ReturnsAsync(expected);

        var sut = new SystemUnderTest(iMock.Object);

        //Act   
        var actual = await sut.MethodUnderTest();

        //Assert
        Assert.AreEqual(expected, actual);
    }

    class ConcreteType {
        public bool isPair { get; set; }
    }

    public interface IService {
        Task<TResult> GetResultAsync<TResult>(Func<string, TResult> transformFunc);
    }

    public class SystemUnderTest {
        private IService instance;

        public SystemUnderTest(IService service) {
            this.instance = service;
        }

        public async Task<object> MethodUnderTest() {
            var result = await instance.GetResultAsync(u => new ConcreteType { isPair = u == "something" });
            return result;
        }
    }
}

【讨论】:

    猜你喜欢
    • 2020-06-06
    • 1970-01-01
    • 1970-01-01
    • 2016-03-15
    • 2017-06-09
    • 2019-10-08
    • 1970-01-01
    • 2013-02-02
    • 1970-01-01
    相关资源
    最近更新 更多