Nunit testing with Mock. Instance of Interface

做~自己de王妃 提交于 2019-12-10 18:55:22

问题


I have the following (simplified) code.

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

and SimpleInjector is used to inject the dependency between _service and its implementation class, like this:

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

As a note, injection and unit testing are new to me so I do not fully understand them, but am learning.

If I run the application through Swagger, all is working fine.

As a note, the Register function is called when I run the application through Swagger.

Now, I am trying to setup some unit tests using NUnit, and am Mocking the IService object like this:

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

which seems to be correct to me so far - although I am not sure?

The problem is that for the unit test, result is always null - I think the is because there is a problem with my Mock of the interface - it does not seem to be finding the method - it never steps into it and does not show up int he debugger.

As a note, for the unit test, the Register method does not get called. I did try calling it to register the dependency, but it does not help.

As I said above, this is all new to me and I am on the edge of my understanding on all of this.

I am out of ideas and do not know where to look from here, so any help would be greatly appreciated.

EDIT:

The original question had the following:

public async Task<IHttpActionResult> Create(string content)

which I have updated to:

public async Task<IHttpActionResult> Create(MyObject object)

Can anyone advise how I can pass in a generic reference to MyObject on the setup, without having to make an instance of this class.

So basically I want to tell it that an instance of this class will be passed in, without creating that instance.

I have tried the following:

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

but it says cannot convert MethodGroup to MyObject

and here is the definition of IService:

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

回答1:


You need to configure the Mock object to return something for IService.method as follows:

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

With the addition of your actual IService definition, you should change the Setup call to:

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



回答2:


The setup method has to be called on the Mock object.

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



回答3:


Using your simplified example

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

Lets assume IService is defined as

public interface IService {
    Task<Result> method(string input);
}

public class Result {
    public bool Succeeded { get; set; }
}

For the unit test you need to setup the mock to fake the actions wanted for the test

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

Given that the method under test is asynchronous you would want to setup the test to be asynchronous as well.



来源:https://stackoverflow.com/questions/41611795/nunit-testing-with-mock-instance-of-interface

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!