本文介绍了Mock上的设置未返回期望值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我遇到的问题的简化版本:

Here is a simplified version of a problem I encountered:

public interface IService
{
    IProvider Provider { get; }
}

public interface IProvider
{
    List<int> Numbers{ get; }
    string Text { get; }
} 

[TestMethod]
public void ServiceTest()
{
    var service = new Mock<IService>();
    var provider = new Mock<IProvider>();

    service.Setup(s => s.Provider).Returns(provider.Object);    // A
    service.Setup(s => s.Provider.Text).Returns("some text");   // B - incorrect

    // they actually meant to do this, instead of 'B'
    // provider.Setup(p => p.Text).Returns("some text"); 

    provider.Setup(p => p.Numbers).Returns(new List<int> { 1, 2, 3 });

    DummyApplicationCode(service.Object);
}

int DummyApplicationCode(IService service)
{
    // will throw, because the Provider was replaced at 'B'
    int shouldBeOne = service.Provider.Numbers.First(); 
    return shouldBeOne;
}

单元测试失败,因为在测试中的应用程序代码中,模拟的IService返回错误的IProvider.

A unit test was failing because way down in the application code under test, the mocked IService was returning the wrong IProvider.

我最终发现了这行代码(请记住,我正在查看的代码并不像上面那么简单),导致这一行,上面标有"B",其他人由于此而添加了该行误会起订量设置.

I eventually spotted the line (bear in mind the code I was looking at was not as simple as above) which had caused it, labelled 'B' above, which someone else had added due to misunderstanding the Moq Setup.

我知道模拟中的后续设置会覆盖先前的设置,但我并未发现此问题,因为违规行的返回是针对单独的子属性.

I'm aware that subsequent Setups on a mock will override previous ones but I hadn't spotted this issue because the Return of the offending line was for a separate sub-property.

我希望这是设计使然,但由于我没想到有人会这样做而使我感到震惊.

I expect this is by design but it threw me as I hadn't anticipated someone would do this.

我的问题:由于"B"处的设置仅与提供者文本的返回有关,为什么服务提供者"属性需要替换该内容哪个定义为"A"?

My question: Since the Setup at 'B' is only concerned with the return of the provider Text, why does the service 'Provider' property need to replace that which was defined at 'A'?

推荐答案

在查看源代码时,这显然是故意的:

This is clearly intentional when looking at the source:

https://github.com/moq/moq4/blob /master/Source/Mock.cs

https://github.com/moq/moq4/blob /master/Source/Interceptor.cs

Setup通过在Interceptor上使用AddCall创建一个呼叫".它包含以下代码块,只要我们创建一个无条件的设置,它就会删除所有以前的设置.甚至有评论.

Setup creates a "call" by using AddCall on Interceptor. This contains the following block of code which, as long as we're creating a non-conditional setup, removes all previous setups. It's even commented.

if (!call.IsConditional)
            {
                lock (calls)
                {
                    // if it's not a conditional call, we do
                    // all the override setups.
                    // TODO maybe add the conditionals to other
                    // record like calls to be user friendly and display
                    // somethig like: non of this calls were performed.
                    if (calls.ContainsKey(key))
                    {
                        // Remove previous from ordered calls
                        InterceptionContext.RemoveOrderedCall(calls[key]);
                    }

                    calls[key] = call;
}

这篇关于Mock上的设置未返回期望值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-28 04:41