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

发布于 2024-10-08 18:23:27 字数 1259 浏览 2 评论 0原文

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

这是我到目前为止所拥有的:

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("牙买加");
    int id = geoService.AddCountry("牙买加");
    

Framework:

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

How do I set up my test method on that mocks a repository which accepts an object?

This is what I have so far:

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); returns an int.

I need to do 2 things:

  1. First test, I need to tell the setup to return an int of 1.
  2. I need to create a second test Insert_Duplicate_Country_Throws_Exception(). In my Setup, how do I tell the repository to throw an error when I do:

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

Framework:

  1. NUnit.
  2. Moq.
  3. ASP.NET MVC - repository pattern.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

你对谁都笑 2024-10-15 18:23:28

您的第一个测试应如下所示:

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

Your first test should look something like this:

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

The second test should look like this:

[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();
    }
}
躲猫猫 2024-10-15 18:23:28

我认为您可能稍微误解了在您提供的两个场景中使用模拟进行测试的目的。

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

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

[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.");
}

在第二种情况下,您希望测试当您尝试添加重复的国家/地区时是否会引发异常。使用模拟执行此操作没有多大意义,因为您将测试的只是您的模拟在添加重复项时的行为,而不是您真正的实现。

I think maybe you are slightly misunderstanding the purpose of testing with mocks in the two scenarios you have supplied.

In the first scenario, you wish to test that 1 is returned when you pass in "Jamaica". This is not a mock test case but a test case for real behaviour as you wish to test a specific input against an expected output i.e. "Jamaica" -> 1. In this situation mocking is more useful to ensure that internally your service calls SaveCountry on the repository with the expected country, and that it returns the value from the call.

Setting up your "SaveCountry" case and then calling "VerifyAll" on your mock is the key. This will assert that "SaveCountry" was indeed called with country "Jamaica", and that the expected value is returned. In this way you have confidence that your service is wired up to your repository as expected.

[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.");
}

In the second scenario you wish to test that an exception is raised when you attempt to add a duplicate country. There's not much point in doing this with a mock as all you will test is that your mock has behaviour when adding duplicates, not your real implementation.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文