Moq是一个匿名类型的函数

时间:2016-09-09 17:07:41

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

我正试图模仿这种方法

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方法与发送的参数匹配。

我正在使用Moq 4

1 个答案:

答案 0 :(得分:3)

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

以下示例在我更改时起作用

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;
        }
    }
}