【问题标题】:How to use Moq to mock and test an IService如何使用 Moq 模拟和测试 IService
【发布时间】:2010-12-17 17:51:09
【问题描述】:

我的服务设置如下:

public interface IMyService
{
      void AddCountry(string countryName); 
}

public class MyService : IMyService
{
      public void AddCountry(string countryName)
      {
          /* Code here that access repository and checks if country exists or not.
             If exist, throw error or just execute. */
      }
}

Test.cs

[TestFixture]
public class MyServiceTest
{
    [Test]
    public void Country_Can_Be_Added()
    { }

    [Test]
    public void Duplicate_Country_Can_Not_Be_Added()
    { }

}

我如何测试 AddCountry 和 moq 存储库或服务。我真的不确定在这里做什么或模拟什么。有人可以帮帮我吗?

我正在使用的框架:

  1. NUnit
  2. 起订量
  3. ASP.NET MVC

【问题讨论】:

    标签: c# nunit moq


    【解决方案1】:

    您为什么需要使用最小起订量?您不需要模拟 IService。在您的情况下,您可以这样编写测试:

    [Test]
    public void Country_Can_Be_Added()
    { 
      new MyService().AddCountry("xy");
    }
    
    [Test]
    public void Duplicate_Country_Can_Not_Be_Added()
    { 
      Assert.Throws<ArgumentException>(() => new MyService().AddCountry("yx"));
    }
    

    如果你有这样的场景,你需要模拟 IRepository:

    interface IRepository { bool CanAdd(string country); }
    class MyService : IService
    {
      private IRepository _service; private List<string> _countries;
      public IEnumerable<string> Countries { get { return _countries; } }
      public X(IRepository service) { _service = service; _countries = new List<string>(); }
      void AddCountry(string x) 
      {  
         if(_service.CanAdd(x)) {
            _conntires.Add(x);
         }
      }      
    }
    

    还有这样的测试:

    [Test]
    public void Expect_AddCountryCall()
    { 
        var canTadd = "USA";
        var canAdd = "Canadd-a";
    
        // mock setup
        var mock = new Mock<IRepository>();
        mock.Setup(x => x.CanAdd(canTadd)).Returns(false);
        mock.Setup(x => x.CanAdd(canAdd)).Returns(true);
    
        var x = new X(mock.Object);
    
        // check state of x
        x.AddCountry(canTadd);
        Assert.AreEqual(0, x.Countires.Count);
    
        x.AddCountry(canAdd);
        Assert.AreEqual(0, x.Countires.Count);
        Assert.AreEqual(0, x.Countires.Count);
        Assert.AreEqual(canAdd, x.Countires.First());
    
        // check if the repository methods were called
        mock.Verify(x => x.CanAdd(canTadd));
        mock.Verify(x => x.CanAdd(canAdd));
    }   
    

    【讨论】:

    • 我想我必须模拟存储库。
    • @Shawn Mclean - 你也可以存根它。我认为我见过比模拟的更多的存根存储库测试。
    • 我建议使用 Assert.Throws 而不是 ExpectedException。
    • 在你的具体测试中,你怎么知道yx已经被添加了?在第一个测试中,您添加了xy。可能想重写第二个测试,先调用new MyService().AddCountry("yx");,然后再写Assert。
    【解决方案2】:

    您测试具体的 MyService。如果它需要一个依赖项(比如在 IRepository 上),您将创建该接口的模拟并将其注入服务。正如所写,测试服务不需要任何模拟。

    创建 IMyService 接口的目的是为了单独测试依赖于 MyService 的其他类。一旦你知道 Repository 可以工作,你就不需要在测试 MyService 时测试它(你模拟或存根它)。一旦您知道 MyService 有效,您就无需在测试 MySomethingThatDependsOnMyService 时对其进行测试。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-12-25
      • 2012-10-02
      • 2023-03-29
      • 1970-01-01
      • 2013-06-13
      • 2020-03-31
      • 2019-02-09
      • 2019-09-27
      相关资源
      最近更新 更多