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

本文关键字:参数 方法 有一个 何用 moq 模拟 | 更新日期: 2023-09-27 18:07:07

我不熟悉嘲弄。我想测试GetById方法是否返回一个带有Id的User对象。在代码下面,我想测试GetById(10)是否返回id = 10的User。

我设置了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
    }
}

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

好吧,正如我在评论中所说的,我不清楚你要测试的代码是什么。我看到了两个选择。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的mock(如问题中所示)并将其传递给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);
}

注。可以看看moq教程和单元测试的艺术书,Part 2 - Core techniques(第47页)-存根,模拟等。

我不太确定你想测试什么。您还可以使用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为服务接口。

要测试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。

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

建议:应该有更好的方法来创建User实例

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

总结一下

类用户实现IUsersUsers有一个带参数IContext的构造函数(或者这里的任何名称)测试类将模拟IContext,但不模拟IUsers。电话用户。GetById并检查输出是否正确。

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