【问题标题】:Nunit testing with Mock. Instance of Interface使用 Mock 进行 Nunit 测试。接口实例
【发布时间】:2017-01-12 11:15:10
【问题描述】:

我有以下(简化的)代码。

public class Controller
{
     private readonly IService _service;

     public Controller(IService service)
     {
         _service = service;
     }

     public async Task<IHttpActionResult> Create(MyObject object)
     {
         var result = _service.method(object);
         if (!result.Succeeded)
         {
            return this.GetErrorResult(object);
         }
     }
}

SimpleInjector 用于注入_service 及其实现类之间的依赖关系,如下所示:

public static void Register(Container container)
{
    container.Register<IService, Service>();
}

作为说明,注入和单元测试对我来说是新的,所以我不完全理解它们,但正在学习。

如果我通过 Swagger 运行应用程序,一切正常。

请注意,当我通过 Swagger 运行应用程序时会调用 Register 函数。

现在,我正在尝试使用 NUnit 设置一些单元测试,并像这样模拟 IService 对象:

var Service = new Mock<IService>();
Controller _controller = new Controller(Service.Object);
_controller.Create(new MyObject object());

到目前为止,这对我来说似乎是正确的 - 虽然我不确定?

问题在于,对于单元测试,result 始终为空 - 我认为这是因为我的接口模拟存在问题 - 它似乎没有找到方法 - 它从未介入并且不会显示在他的调试器中。

请注意,对于单元测试,Register 方法不会被调用。我确实尝试调用它来注册依赖项,但它没有帮助。

正如我上面所说,这对我来说是全新的,我对所有这些都处于理解的边缘。

我没有想法,不知道从哪里看,所以任何帮助将不胜感激。

编辑:

原来的问题如下:

public async Task<IHttpActionResult> Create(string content)

我已经更新到:

public async Task<IHttpActionResult> Create(MyObject object)

谁能告诉我如何在设置中传递对MyObject 的通用引用,而不必创建此类的实例。

所以基本上我想告诉它这个类的一个实例将被传入,而不是创建那个实例。

我尝试了以下方法:

Service.Setup(x => x.method(It.IsAny<MyObject>())

but it says cannot convert MethodGroup to MyObject

这里是IService的定义:

public interface IService
{
      IdentityResult method(ApplicationUser user, UserLoginInfo login);
}

【问题讨论】:

  • 对。你需要设置模拟来做你想让它为测试做的事情。在这里查看快速入门github.com/Moq/moq4/wiki/Quickstart
  • 您是否对模拟对象进行了模拟设置?
  • @Alex,您可能需要放弃简化的示例并确切地询问您需要什么。因为我们只会猜测。看起来您正在使用广泛的 Asp.Net Identity 框架。所以请缩小范围
  • 你不会看到你的单元测试命中了你的Register 方法,因为你的测试没有运行那个代码;他们单独测试您的被测类。这是一件好事:在单元测试时不要使用 DI 容器。

标签: c# mocking nunit moq simple-injector


【解决方案1】:

您需要配置Mock 对象以返回IService.method 的内容,如下所示:

var Service = new Mock<IService>();
Service.Setup(x => x.method(It.IsAny<string>())
    .Returns<string>(str => **whatever result you need**);

添加实际的IService 定义后,您应该将Setup 调用更改为:

Service.Setup(x => x.method(It.IsAny<ApplicationUser>(), It.IsAny<UserLoginInfo>())
    .Returns<ApplicationUser, UserLoginInfo>((user, login) => new IdentityResult(true));

【讨论】:

  • 请将IService的定义添加到您的问题中。
  • 我已经发布了 IService 定义
  • 谢谢您 - 非常感谢您的帮助。我有这个:Service.Setup(x => x.method(It.IsAny, It.IsAny)) - 如此接近!
  • @Alex 将来会提供minimal reproducible example 强调完整,这样您就可以获得更好的答案,而无需大量来回要求澄清。
【解决方案2】:

必须在 Mock 对象上调用 setup 方法。

var Service = new Mock<IService>();
Service.Setup(x=>x.method("argument")).Returns(YourReturnObject)
Controller _controller = new Controller(Service.Object);

【讨论】:

    【解决方案3】:

    使用您的简化示例

    public class Controller
    {
         private readonly IService _service;
    
         public Controller(IService service)
         {
             _service = service;
         }
    
         public async Task<IHttpActionResult> Create(string content)
         {
             var result = await _service.method(content);
             if (!result.Succeeded)
             {
                return this.GetErrorResult(result);
             }
             return Ok();
         }
    }
    

    假设 IService 被定义为

    public interface IService {
        Task<Result> method(string input);
    }
    
    public class Result {
        public bool Succeeded { get; set; }
    }
    

    对于单元测试,您需要设置模拟来伪造测试所需的操作

    public async Task Controller_Given_Content_Should_Return_Ok() {
        //Arrange
        var input = "content";
        var mockService = new Mock<IService>();
        mockService
            .Setup(m => m.method(input))
            .ReturnAsync(new Result { Succeeded = true }); 
        var _controller = new Controller(mockService.Object);
    
        //Act
        var result = await _controller.Create(input);
    
        //Assert
        Assert.IsNotNull(result);
        Assert.IsInstanceOfType(result,typeof(OkResult));
    }
    

    鉴于被测方法是异步的,您可能希望将测试也设置为异步。

    【讨论】:

      猜你喜欢
      • 2018-01-11
      • 2018-08-23
      • 1970-01-01
      • 2022-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多