模拟控制器对象方法 returns 结果中的空值

Mocked controller object method returns Null value in Result

我正在使用 xUnit 工具在 Dot net core 中编写单元测试用例。在此示例中,我还尝试模拟控制器的受保护方法。

public interface ITestService {
    string GetString(string testString);
}

public class TestModel {
    string testValue { get; set; }
}

public class TestController : Controller
{
    readonly ITestService testService;

    public TestController() {
    }

    public TestController(ITestService _testService) {
        testService = _testService;
    }

    [HttpPost]
    public async Task<IActionResult> Post([FromBody]TestModel testModel)
    {
        string test = GetString("testNew");
        await Task.Run(() => "test");
        return Ok(test);
    }

    protected virtual string GetString(string testString)
    {
        return "test" + testString;
    }
}

因此,我需要模拟控制器本身,以便在其调用方法中对受保护的方法进行单元测试。

但是当我使用 Mocked 对象调用控制器的方法时,我得到了 Null 值。

public class TestControllerTest
{
    private Mock<ITestService> MockTestService { get; }
    TestController controller { get; }

    public TestControllerTest()
    {
        MockTestService = new Mock<ITestService>();

        controller = new TestController(MockTestService.Object);
    }

    [Fact]
    public void Post_TakesTestString_ReturnsString()
    {
        var MockController = new Mock<TestController>(MockTestService.Object);
        MockController.Protected().Setup<string>("GetString", ItExpr.IsAny<string>()).Returns("testMockValue").Verifiable();

        var result = MockController.Object.Post(new TestModel() { }).Result;
        // result returns NULL value

        MockController.Protected().Verify("GetString", Times.Once(), ItExpr.IsAny<string>());
    }
}

我的问题在代码的下面一行 -

var result = MockController.Object.Post(new TestModel() { }).Result;

哪个 returns 空值,我预计,行应该 return OkObjectResult 带有测试字符串。

由于被测对象class也在mock中,需要调用实际的目标方法

启用 CallBase 属性 设置为 true 否则默认行为是 return null 对于没有设置的成员被调用。

例如

public class TestControllerTest {

    [Fact]
    public async Task Post_TakesTestString_ReturnsString() {
        //Arrange
        var MockTestService = new Mock<ITestService>();
        var MockController = new Mock<TestController>(MockTestService.Object) {
            CallBase = true //<--
        };
        MockController.Protected().Setup<string>("GetString", ItExpr.IsAny<string>()).Returns("testMockValue").Verifiable();
        TestController controller = MockController.Object;

        //Act
        var result = await controller.Post(new TestModel() { });

        //Assert    
        MockController.Protected().Verify("GetString", Times.Once(), ItExpr.IsAny<string>());
    }
}