It.Is ... () функциясы анонимді функциядан шақырылса, неге Moq орнату/тексерушіні тексермейді

Орнату/Тексеруді moq арқылы сәйкестендіру үшін өте күрделі өрнектер ағынын құруды оңайлатуға тырысқанда, мен біртүрлі мінез-құлыққа жүгірдім.

Төменде анықталған қарапайым интерфейсті шатастырамын деп ойлаймын

public interface IService
    int Send(int value);

Келесі код 5 сынақтан тұрады. mockSender.Setup (...) әр бір сынақ. Сынақтардың сәтсіздікке ұшырағаны неге сәтсіз болғанын түсіндіре ала ма?

public void TestInlineSetup()
    const int expected = 5;
    var mockSender = new Mock(MockBehavior.Loose);

    mockSender.Setup(s => s.Send(It.IsAny())).Returns(expected);

    var sendMatch = It.IsAny();
    mockSender.Setup(s => s.Send(sendMatch)).Returns(expected);

    mockSender.Setup(s => s.Send(SendMatchFromMethod())).Returns(expected);

    var sendMatch = SendMatchFromMethod();
    mockSender.Setup(s => s.Send(sendMatch)).Returns(expected);

    //fails (this is somewhat contrived, but I have reasons for wanting to curry this)
    mockSender.Setup(s => s.Send(SendMatchFromCurriedMethod()())).Returns(expected);

    Assert.That(mockSender.Object.Send(expected), Is.EqualTo(expected));

public static int SendMatchFromMethod()
    return It.IsAny();

public static Func SendMatchFromCurriedMethod()
    return() => It.IsAny();

Edit: I know about Mock.Of<..>(..) and normally prefer to use it but in this case it is not an option.


2 жауаптар

Мәселе параметрді сәйкестендіргішті құру үшін берілген өрнек ағашын талдауға тырысады. Мұнда дерек көзін таба аласыз: - /source/browse/trunk/Source/MatcherFactory.cs

Көзге сілтеме жасай отырып: -

  • It.IsAny matchers are detected by compiling and executing the expression that is passed as the parameter and looking for any matches (see here).
  • The above step only takes place for method calls and member accesses

Міне, сол себепті ...

  1. Second test fails because the It.IsAny method has been evaluated outside of the matcher factory. As such you have a MemberAccess expression to 0.
  2. Third test passes because SendMatchFromMethod is treated as a method call expression and the call is evaluated inside the MatcherFactory.
  3. Fourth test fails for the same reason as the second, the function has already evaluated and Moq can't detect you've actually called It.Is
  4. Fifth test fails because the Expression is treated as a Function Invocation and Moq does not perform the matcher check for this type of expression.

Төртінші сынақ, шыншыл болу керек, өтіп кетуі керек, және ол тек қана бір шеткі жағдай болғандықтан ғана қалдырылуы мүмкін.

Finally Match.Create or MatchAttribute can be used to deal with complex predicates, perhaps they might fit your use case?


This seems to be very similar to a situation I ran into a while ago: Moq unit test with It.IsAny() fails

The issue seems to be with when It.IsAny() gets evaluated. With the 2 tests that pass, it's getting evaluated inside of Setup(...), which works fine. In the first 2 tests that fail, it's getting evaluated outside the scope of Setup(...), so it fails to evaluate correctly. What's probably getting stored in your variable is the result of It.IsAny(), which will be the default value for an int (0).

I don't know the exact reason why the last test would fail, but it could be either that as an optimization your static Func gets evaluated before Setup(...) executes, or it could be that it gets evaluated after Setup(...), but either way it's happening outside of Setup(...).

Дұрыс, сіз оны пайдалана алмайсыз.
қосылды автор aqwert, көзі