如何用moq模拟带有一个参数的方法

时间:2013-04-03 09:06:23

标签: c# .net mocking moq

我不熟悉嘲笑。我想测试我的方法GetById是否返回一个具有Id的对象User。在代码下面,我想测试GetById(10)是否返回i​​d为10的用户。

我设置了moq(我希望它是正确的)但是如何执行moq?

谢谢,

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

4 个答案:

答案 0 :(得分:0)

我不太确定你想测试什么。你也有Mock类,有一些你没有描述的方法。

然而,回答你关于嘲笑的问题。考虑这个课程:

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

使用它:

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

我在此示例中的假设是Mock<IUsers>是一个存储库,MyMoq是一个服务类。此外,IUser是实体接口,IUsers是服务接口。

答案 1 :(得分:0)

要测试userMock.Object,应该返回实际的模拟IUsers对象。

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

在上面的代码中,newUserObject只创建了User的新实例。 要测试GetById方法,您需要再次调用它并断言。

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

建议: 应该可以更好地创建User实例。

答案 2 :(得分:0)

GetById应该在它自己的类中(可能称为Users),如果这是正在测试的内容。然后,用户可以在构造函数中接受上下文。然后模拟此上下文以返回存根数据。

总结

实施IUsers的类用户 用户有一个带参数IContext的构造函数(或者在这里调用的任何东西) 测试类会模拟IContext而不是IUsers。 调用users.GetById并检查输出是否正确。

设置上下文的方式取决于它的上下文类型,但请参阅https://cuttingedge.it/blogs/steven/pivot/entry.php?id=84

答案 3 :(得分:0)

好吧,正如我在评论中所说,我不清楚你要测试的代码是什么。我在这里看到两个选项。 1)Users类实现IUsers接口,您的目的是测试GetById(int)方法的实现。 在这种情况下,您不需要模拟'Users#GetById(id)'方法,您只需要调用它并检查结果。 代码应类似于:

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)您的Users#GetById(int)方法应该调用IUsers#GetById(int)并返回结果。在这种情况下,您需要创建IUsers的模拟(如您所示)并将其传递给Users。代码应该是(抱歉可能重复):

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

P.S。查看moq tutorialThe Art of Unit Testing本书,Part 2 - Core techniques(第47页) - 存根,模拟等等可能很有用。