简体   繁体   English

如何使用Moq模拟具有一个参数的方法

[英]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. 我想测试我的方法GetById是否返回带有ID的对象User。 Below the code, I'd like test if the GetById(10) return me an User with id = 10. 在代码下面,我想测试一下GetById(10)是否向我返回一个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. 您还拥有Mock类,其中包含一些您未描述的方法。

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. 在此示例中,我的假设是Mock<IUsers>是存储库,而MyMoq是服务类。 Also, IUser is an Entity Interface, and IUsers is a service interface. 另外, IUser是实体接口,而IUsers是服务接口。

To test userMock.Object should return the actual mocked IUsers object. 要测试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); 

In the above code, newUserObject has only created a new instance of User . 在上面的代码中, newUserObject仅创建了User的新实例。 To test your GetById method, you need to call it again and Assert. 要测试您的GetById方法,您需要再次调用它并断言。

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. 建议:应该有更好的方法来创建User实例。

GetById should be in it's own class (probably called Users) if that is what is being tested. 如果正在测试,则GetById应该在其自己的类(可能称为Users)中。 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. 实现IUsers的类Users Users具有一个带有参数IContext的构造函数(或此处将要调用的任何参数)测试类将模拟IContext但不模拟IUsers。 Call users.GetById and check the output is correct. 调用users.GetById并检查输出是否正确。

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 . 设置上下文的方式取决于上下文的类型,但是请参见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. 1) Users类实现IUsers接口,您的目的是测试GetById(int)方法的实现。 In such case you do NOT need to mock the 'Users#GetById(id)' method, you just need to call it and check the result. 在这种情况下,您无需模拟'Users#GetById(id)'方法,只需调用它并检查结果即可。 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. 2)您的Users#GetById(int)方法应该调用IUsers#GetById(int)并返回结果。 In such case you need to create mock of IUsers (as you've shown in question) and pass it to Users . 在这种情况下,您需要创建IUsers模拟(如您所显示的那样)并将其传递给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. ps可能对阅读moq教程单元测试的艺术书籍, Part 2 - Core techniques (第47页)-存根,模拟等很有帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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