简体   繁体   English

如何获取在模拟类内部调用的方法的结果

[英]How to get result of method called inside of a mocked class

There is a way to get the result returned from a method called into a mocked object?有没有办法获得从调用到模拟对象的方法返回的结果?

For example, if I have the following classes and an interface:例如,如果我有以下类和一个接口:

DoSomethingClass.cs DoSomethingClass.cs

public class DoSomethingClass
{
  
  IInternalClass _intClass;

  public DoSomethingClass(IInternalClass intClass)
  {
    _intClass = intClass;
  }
  
  void DoSomething(int number)
  {
    // do some transformation to the number, e.g.
    var transformedNumber = number * (number - 1);
    
    var x = _intClass.IsEven(transformedNumber);

    // do something else
  }
}

InternalClass.cs内部类.cs

public interface IInternalClass
{
  bool IsEven(int number);
}

public class InternalClass: IInternalClass
{
  
  public InternalClass();
  
  public bool IsEven(int number)
  {
    return number % 2 == 0;
  }
}

And a test class:和一个测试类:

Tests.cs测试.cs

public class Tests
{
  [Fact]
    public async Task test_something()
    {

        //PREPARE
        var request = 10

        var internalMock = new Mock<IInternalClass>();
        var classToTest = new DoSomethingClass(internalMock.Object);

        // ACT

        await classToTest.DoSomething(request);

        //ASSERT

        //Here I want to check if the method IsEven of the internal class return the right result
    }
  }
}

What I want to assert is the return value of the method IsEven of the InternalClass called inside the main method DoSomething , there is no way that I can know the transformedNumber calculated inside this method and passed to IsEven .我要断言的是在主方法DoSomething调用的InternalClass的方法IsEven的返回值,我无法知道在此方法中计算出的transformedNumber并传递给IsEven

NOTE: I use the Moq library to mock object.注意:我使用Moq库来模拟对象。

Excuse me for the stupid example above, but I don't have any simple real code to show here, however I hope this can be sufficient to understand the question.请原谅我上面那个愚蠢的例子,但我没有任何简单的真实代码可以在这里展示,但是我希望这足以理解这个问题。

I am assuming that you want to verify that your IsEven method is called on the mocked IInternalClass?我假设您想验证是否在模拟的 IInternalClass 上调用了 IsEven 方法?

If that is the case then you can use the Verify method on the mock as follows:如果是这种情况,那么您可以在模拟上使用验证方法,如下所示:

[Fact]
public void DoSomething_Verify()
{
    var request = 10;
    var internalMock = new Mock<IInternalClass>();
    var classToTest = new DoSomethingClass(internalMock.Object);

    classToTest.DoSomething(request);

    //Verify that the mock is invoked with the expected value, the expected number of times
    internalMock.Verify(v => v.IsEven(90), Times.Once);
    //There are lots of other options for Times, e.g. it is never called with an unexpected value maybe.
    internalMock.Verify(v => v.IsEven(91), Times.Never);
}

Also to call the DoSomething method with await you would need to change the method signature as follows:同样要使用 await 调用 DoSomething 方法,您需要按如下方式更改方法签名:

public async Task DoSomethingAsync(int number)
{
    // do some transformation to the number, e.g.
    var transformedNumber = number * (number - 1);

    var x = _intClass.IsEven(transformedNumber);

    // do something else
}

Then you can create a unit test like this:然后你可以像这样创建一个单元测试:

[Fact]
public async void DoSomething_VerifyAsync()
{
    var request = 10;
    var internalMock = new Mock<IInternalClass>();
    var classToTest = new DoSomethingClass(internalMock.Object);

    //To call the DoSomething method with await the method needs the async Task and a good convention is to append Async to the name
    await classToTest.DoSomethingAsync(request);

    //Another slightly more generic option is to verify that the mock was called with and int exactly n Times
    internalMock.Verify(v => v.IsEven(It.IsAny<int>()), Times.Exactly(1));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM