Nunit用模拟测试。接口实例

时间:2017-01-12 11:15:10

标签: c# mocking nunit moq simple-injector

我有以下(简化)代码。

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总是为空 - 我认为这是因为我的Mock接口存在问题 - 它似乎没有找到方法 - 它从不步骤进入它并且没有显示在调试器中。

注意,对于单元测试,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);
}

3 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:2)

您需要配置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));

答案 2 :(得分:2)

使用简化示例

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

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