代码之家  ›  专栏  ›  技术社区  ›  ruffin

如何在“real”方法中调用mocked方法时使用params?

  •  1
  • ruffin  · 技术社区  · 6 年前

    我在模仿一个有这个签名的方法:

    public async Task<string> Upsert(Preferences prefs, string id)
    

    ... 我想用我在测试类中已经定义的方法来Moq它。也就是说,我 不要 要使用lambda表达式。

    如何将发送到模拟方法的参数传递给“real”方法,就像使用lambda表达式一样?


    调用lambda表达式(参数与调用时发送的参数匹配)

    也就是说,如果这是我用lambda写的话。。。

    _mockDataAdapater
        .Setup(x => x.Upsert(It.IsAny<Preferences>(), It.IsAny<string>()))
        .Returns((Preferences p, string id) =>
        {
            return Task.FromResult(id);    
            // see how I can use  ^^^^  the `id` param here?
        });
    

    id 调用中的参数。

    public async void testMe()
    {
        var output  = await _mockDataAdapater.Object.Upsert(new Preferences(), "hello");
    
        System.Diagnostics.Debug.WriteLine(output);    // <<< "hello" in this case.
    }
    

    这就是我想要的。

    调用“real”函数(总是“spam”)

    我该怎么做 指定参数的值 p 身份证件 是否仍使用此语法?

    // This is what I want to use instead of a lambda expression.
    private async Task<string> _upsertMock(Preferences prefs, string id)
    {
        return await Task.Run(() =>
        {
            return id;
        });
    }
    
    //...
    
    public MyClassConstructor()
    {
        // Set up mock objects...
    
        _mockDataAdapater
            .Setup(x => x.Upsert(It.IsAny<Preferences>(), It.IsAny<string>()))
            .Returns(_upsertMock(new Preferences(), "spam")); 
            // Both params are hard coded! ^^^^^^^^^^^^^ 
            // 
            // (Rather, if I don't insert hard-coded params here, I can't
            //  get things to build. How do I hook up to the It.IsAnys?)
    } 
    

    这个 总是 testMe 打电话。糟糕的最小起订量!

    public async void testMe()
    {
        var output  = await _mockDataAdapater.Object.Upsert(new Preferences(), "hello");
    
        System.Diagnostics.Debug.WriteLine(output);    // <<< now always "spam"
    }
    

    说清楚点,我知道为什么我总是 "spam" . 这是有道理的。但是很臭。


    这是可行的,但感觉不对

    我可以 wrap my function in another function ...

    _mockDataAdapater
        .Setup(x => x.Upsert(It.IsAny<Preferences>(), It.IsAny<string>()))
        .Returns((Preferences p, string id) =>
        {
            return _upsertMock(p, id);
        });
    

    包装是我唯一能进入的方式吗 身份证件

    1 回复  |  直到 6 年前
        1
  •  1
  •   Nkosi    6 年前

    [TestClass]
    public class MyTestClass {
        public class Preferences {
    
        }
        public interface IInterface {
            Task<string> Upsert(Preferences prefs, string id);
        }
    
        public Task<string> _upsertMock(Preferences prefs, string id) {
            return Task.Run(() => {
                return id;
            });
        }
    
        [Test]
        public async Task MyTestMethod() {
    
            var mock = new Mock<IInterface>();
            mock
                .Setup(_ => _.Upsert(It.IsAny<Preferences>(), It.IsAny<string>()))
                .Returns((Func<Preferences, string, Task<string>>)_upsertMock);
    
            var expected = "123";
    
            var actual = await mock.Object.Upsert(null, expected);
    
            actual.Should().Be(expected);
        }
    }
    

    .Returns((Func<Preferences, string, Task<string>>)_upsertMock);
    

    所以正确的 .Returns 设置期间使用过载。