使用Moq模拟返回值的存储库

时间:2010-12-19 01:48:30

标签: unit-testing nunit moq

如何在mocks上设置我的测试方法接受对象的存储库?

这是我到目前为止所做的:

Service.cs

    public int AddCountry(string countryName)
    {
        Country country = new Country();
        country.CountryName = countryName;
        return geographicsRepository.SaveCountry(country).CountryId;
    }

test.cs中

    [Test]
    public void Insert_Country()
    {
        //Setup
        var geographicsRepository = new Mock<IGeographicRepository>();

        geographicsRepository.Setup(x => x.SaveCountry(It.Is<Country>(c => c.CountryName == "Jamaica"))); //How do I return a 1 here?

        GeographicService geoService = new GeographicService(geographicsRepository.Object);

        int id = geoService.AddCountry("Jamaica");

        Assert.AreEqual(1, id);
    }

SaveCountry(Country country);返回一个int。

我需要做两件事:

  1. 首先测试,我需要告诉设置返回1的int。
  2. 我需要创建第二个测试Insert_Duplicate_Country_Throws_Exception()。在我的安装程序中,当我这样做时,如何告诉存储库抛出错误:

    int id = geoService.AddCountry("Jamaica");
    int id = geoService.AddCountry("Jamaica");
    
  3. 框架:

    1. NUnit的。
    2. 起订量。
    3. ASP.NET MVC - 存储库模式。

2 个答案:

答案 0 :(得分:8)

你的第一次测试应该是这样的:

[Test]
public void Insert_Country()
{
    Mock<IGeographicRepository> geographicsRepository = new Mock<IGeographicRepository>();
    GeographicService geoService = new GeographicService(geographicsRepository.Object);

    // Setup Mock
    geographicsRepository
        .Setup(x => x.SaveCountry(It.IsAny<Country>()))
        .Returns(1);

    var id = geoService.AddCountry("Jamaica");

    Assert.IsInstanceOf<Int32>(id);
    Assert.AreEqual(1, id);
    geographicsRepository.VerifyAll();
}

第二次测试应如下所示:

[Test]
public void Insert_Duplicate_Country_Throws_Exception()
{
    Mock<IGeographicRepository> geographicsRepository = new Mock<IGeographicRepository>();
    GeographicService geoService = new GeographicService(geographicsRepository.Object);

    // Setup Mock
    geographicsRepository
        .Setup(x => x.SaveCountry(It.IsAny<Country>()))
        .Throws(new MyException());

    try
    {
        var id = geoService.AddCountry("Jamaica");
        Assert.Fail("Exception not thrown");
    }
    catch (MyException)
    {
        geographicsRepository.VerifyAll();
    }
}

答案 1 :(得分:1)

我想在您提供的两种情况下,您可能会对使用模拟测试的目的略有误解。

在第一个场景中,您希望测试在传入“牙买加”时返回1。这不是模拟测试用例,而是实际行为的测试用例,因为您希望根据预期输出测试特定输入,即“牙买加” - &gt; 1.在这种情况下,模拟更有用于确保您的内部服务在具有预期国家/地区的存储库上调用SaveCountry,并且它会从调用返回值。

设置“SaveCountry”案例然后在模拟上调用“VerifyAll”是关键。这将断言“SaveCountry”确实在国家“牙买加”被调用,并且返回预期值。通过这种方式,您可以确信您的服务已按预期连接到存储库。

[Test]
public void adding_country_saves_country()
{
    const int ExpectedCountryId = 666;

    var mockRepository = new Mock<IGeographicRepository>();

    mockRepository.
      Setup(x => x.SaveCountry(It.Is<Country>(c => c.CountryName == "Jamaica"))).
      Returns(ExpectedCountryId); 

    GeographicService service= new GeographicService(mockRepository.Object);

    int id = service.AddCountry(new Country("Jamaica"));

    mockRepo.VerifyAll();

    Assert.AreEqual(ExpectedCountryId, id, "Expected country id.");
}

在第二种方案中,您希望测试在尝试添加重复的国家/地区时引发异常。使用模拟执行此操作并没有太大意义,因为您将测试的是,在添加重复项时,您的模拟行为,而不是您的实际实现。