模拟的控制器对象方法在结果中返回Null值

时间:2019-08-19 12:47:57

标签: c# unit-testing mocking moq xunit

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

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;
    }
}

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

但是当我使用模拟对象调用控制器的方法时,我得到的是 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;

我希望哪个返回Null值,行应该返回带有测试字符串的OkObjectResult

1 个答案:

答案 0 :(得分:0)

由于正在模拟被测主题类,因此需要调用实际的目标方法。

启用CallBase属性为true的情况,否则默认行为是为未设置要调用的成员返回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>());
    }
}