简体   繁体   中英

How mock a method with one parameter with moq

I'm not familiar with mocking. I'd like test if my method GetById return me an object User with an Id. Below the code, I'd like test if the GetById(10) return me an User with id = 10.

I set the moq (I hope it's correct) but how execute the moq ?

Thanks,

[TestMethod]
public void MyMoq()
{
    var userMock = new Mock<IUsers>();
    userMock.Setup(x => x.GetById(10)).Returns(new User());

    //After ?
    new Users().GetById(10);
}

public interface IUsers
{
    IUser GetById();
}

public IUser GetById(int id)
{
    using (var context = ....)
    {
        //code here

        //return user here
    }
}

I don't quite sure what you want to test. You also has Mock class with some methods that you don't describe.

However, answering your question about mocking. Consider this class:

public class MyMoq : IUsers
{
  private readonly Mock<IUsers> userMock;
  public MyMoq(Mock<IUsers> userMock){
    this.userMock = userMock;
  }

  [TestMethod]
  public IUser GetById()
  {
      userMock.Setup(x => x.GetById(10)).Returns(new User());

      //After ?
      return new UsersDb().GetById(10);
  }
}

To use it:

MyMoq moq = new MyMoq(new Mock<IUsers>());
User u = moq.GetById();

My assumption in this example is Mock<IUsers> is a repository and MyMoq is a service class. Also, IUser is an Entity Interface, and IUsers is a service interface.

To test userMock.Object should return the actual mocked IUsers object.

var userMock = new Mock<IUsers>();
userMock.Setup(x => x.GetById(10)).Returns(new User());

var mockobject = userMock.Object;

//Returns your mocked new User() instance
var newUserObject = mockobject.GetById(10); 

In the above code, newUserObject has only created a new instance of User . To test your GetById method, you need to call it again and Assert.

Assert.AreEqual(newUserObject.GetById(20).ID, 20);  //Assume User has a property ID

Suggestion: It should be possible to have a better way to create the User instance.

GetById should be in it's own class (probably called Users) if that is what is being tested. Users could then accept a context in the constructor. Then mock this context to return stubbed data.

So in summary

Class Users implementing IUsers Users has a constructor with parameter IContext (or whatever it would be called here) Test class would mock IContext but not IUsers. Call users.GetById and check the output is correct.

The way you would set up your context depends on what type of context it is, but see https://cuttingedge.it/blogs/steven/pivot/entry.php?id=84 .

Alright, as I said in comments, it's not clear for me what code you're trying to test. I see two options here. 1) The Users class implements IUsers interface and your intention is to test implementation of GetById(int) method. In such case you do NOT need to mock the 'Users#GetById(id)' method, you just need to call it and check the result. The code should look similar to:

interface IUser
{
    int Id { get; }
}
class User : IUser
{
    public int Id { get;set; }
}

interface IUsers
{
    IUser GetById(int id);
}
class Users : IUser
{
    public IUser GetById(int id)
    {
        // TODO: make call db call
        // TODO: parse the result
        // TODO: and return new User instance with all the data from db
        return new User{ Id = id };
    }
}

[TestMethod]
public void MyMoq()
{   
    // TODO: prepare/mock database. That's whole another story.

    var users = new Users();

    // act
    var user = users.GetById(10);

    // assert
    Assert.AreEqual(10, user.Id);
}

2) Your Users#GetById(int) method is supposed to call the IUsers#GetById(int) and return the result. In such case you need to create mock of IUsers (as you've shown in question) and pass it to Users . The code should be(sorry for possible duplication):

interface IUser
{
    int Id { get; }
}
class User : IUser
{
    public int Id { get;set; }
}

interface IUsers
{
    IUser GetById(int id);
}
class Users : IUser
{
    private readonly IUser _users;
    public Users(IUser users)
    {
        _users = users;
    }

    public IUser GetById(int id)
    {
        // next line of code is to be tested in unit test
        return _users.GetById(id);
    }
}

[TestMethod]
public void MyMoq()
{   
    var usersMock = new Mock<IUsers>();
    usersMock.Setup(x => x.GetById(10)).Returns(new User());

    var users = new Users(usersMock.Object);

    // act
    var user = users.GetById(10);

    // assert
    Assert.AreEqual(10, user.Id);
}

ps Could be useful to take a look at moq tutorial and The Art of Unit Testing book, Part 2 - Core techniques (page 47) - stubs, mocks, etc.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM