使用最小起订量模拟同一接口中的方法

发布于 2024-10-03 12:59:59 字数 1620 浏览 1 评论 0原文

我想测试一个服务中的方法。该方法调用同一类中的另一个方法。该方法已经过测试,所以我想模拟该方法。

这是我的设置:

private readonly Mock<INewsLetterRepository> _mockNewsLetterRepository;
private readonly Mock<INewsLetterService> _mockNewsLetterService;
private readonly INewsLetterService _newsLetterService;

public NewsLetterServiceTest()
{
    _mockNewsLetterRepository = new Mock<INewsLetterRepository>();
    _mockNewsLetterService = new Mock<INewsLetterService> {CallBase = true};
    _newsLetterService = new NewsLetterService(_mockNewsLetterRepository.Object);
}

这是我正在使用的测试:

[TestMethod]
public void CreateNewsLetter_Should_Return_Empty_NewsLetter()
{
    var template = new Template
                   {
                       PlaceHolders = new List<TemplatePlaceholder>()
                   };
    var newsLetter = new NewsLetter {Template = template};
    const string content = "<html><body><!--BROWSER--></body></html>";
    _mockNewsLetterService.Setup(x => x.BuildNewsLetterHTML(It.IsAny<NewsLetter>())).Returns(content);

    var actual = _mockNewsLetterService.Object.CreateNewsLetter(newsLetter);
    Assert.AreEqual(content, actual);
}

现在的问题是我正在嘲笑的函数:BuildNewsLetterHTML 返回 null 而不是它应该返回的内容。

这是我想要测试的函数的简化版本:

public string CreateNewsLetter(NewsLetter newsLetter)
{
    var newsletterHTML = BuildNewsLetterHTML(newsLetter);
    return newsletterHTML;
}

所以问题是,至少在我看来,我模拟的函数没有返回它应该返回的内容字符串。 Assert.AreEqual 测试失败,因为实际值为 null。你们中有人知道为什么实际为空吗?

提前致谢。

I have a method in a service which I want to test. That method calls another method in the same class. This method is already tested so I want to mock that method.

This is my setup:

private readonly Mock<INewsLetterRepository> _mockNewsLetterRepository;
private readonly Mock<INewsLetterService> _mockNewsLetterService;
private readonly INewsLetterService _newsLetterService;

public NewsLetterServiceTest()
{
    _mockNewsLetterRepository = new Mock<INewsLetterRepository>();
    _mockNewsLetterService = new Mock<INewsLetterService> {CallBase = true};
    _newsLetterService = new NewsLetterService(_mockNewsLetterRepository.Object);
}

And this is the test I am using:

[TestMethod]
public void CreateNewsLetter_Should_Return_Empty_NewsLetter()
{
    var template = new Template
                   {
                       PlaceHolders = new List<TemplatePlaceholder>()
                   };
    var newsLetter = new NewsLetter {Template = template};
    const string content = "<html><body><!--BROWSER--></body></html>";
    _mockNewsLetterService.Setup(x => x.BuildNewsLetterHTML(It.IsAny<NewsLetter>())).Returns(content);

    var actual = _mockNewsLetterService.Object.CreateNewsLetter(newsLetter);
    Assert.AreEqual(content, actual);
}

Now the problem is that the function I am mocking: BuildNewsLetterHTML returns null instead of the content it supposed to return.

Here is a simplified version of the function I want to test:

public string CreateNewsLetter(NewsLetter newsLetter)
{
    var newsletterHTML = BuildNewsLetterHTML(newsLetter);
    return newsletterHTML;
}

So the problem is that, at least as I see it, is that the function I mock doesn't return the content string it supposed to return. The test fails on Assert.AreEqual because the actual is null. Any of you have any idea why actual is null?

Thanks in advance.

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

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

发布评论

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

评论(1

极致的悲 2024-10-10 12:59:59

问题似乎是您正在调用 Mock's CreateNewsLetter 方法,该方法尚未设置,并且似乎也是您正在测试的方法。您不应该针对您的假货进行测试,它们应该替换生产代码以帮助测试其他代码。

我建议您使用 在这种情况下,提取并覆盖模式,因为您希望在具有正在测试的方法的同一类的方法中导致假实现。

起订量在某些情况下很好,但我认为在情况需要时使用小的可读存根没有什么问题。

public class YourTestClass
{
    [TestMethod]
    public void CreateNewsLetter_Should_Return_Empty_NewsLetter()
    {
        var template = new Template
        {
            PlaceHolders = new List<TemplatePlaceholder>()
        };
        var newsLetter = new NewsLetter { Template = template };

        const string content = "<html><body><!--BROWSER--></body></html>";

        INewsletterService service = new BuildNewsLetterStub(content);
        string actual = service.CreateNewsLetter(newsLetter);

        Assert.AreEqual(content, actual);
    }
}


public class BuildNewsLetterStub : NewsLetterService
{
    private string _letter;

    public BuildNewsLetterStub(string letter)
    {
        _letter = letter;
    }
    public override string BuildNewsLetterHTML(NewsLetter newsLetter)
    {
        return _letter;
    }
}

要覆盖 BuildNewsLetterHTML,必须将其标记为虚拟。

It seems the problem is you are calling Mock<T>'s CreateNewsLetter method which has not been set up, and which also seems to be your method under test. You are not supposed test against your fakes, they are supposed to substitute out production code to assist in testing other code.

I suggest you use the extract and override pattern in this case, since you are wanting to cause fake implementation in a method of the same class that has a method under test.

Moq is great in some cases but I don't think there is anything wrong with using a small readable stub when the situation calls for it.

public class YourTestClass
{
    [TestMethod]
    public void CreateNewsLetter_Should_Return_Empty_NewsLetter()
    {
        var template = new Template
        {
            PlaceHolders = new List<TemplatePlaceholder>()
        };
        var newsLetter = new NewsLetter { Template = template };

        const string content = "<html><body><!--BROWSER--></body></html>";

        INewsletterService service = new BuildNewsLetterStub(content);
        string actual = service.CreateNewsLetter(newsLetter);

        Assert.AreEqual(content, actual);
    }
}


public class BuildNewsLetterStub : NewsLetterService
{
    private string _letter;

    public BuildNewsLetterStub(string letter)
    {
        _letter = letter;
    }
    public override string BuildNewsLetterHTML(NewsLetter newsLetter)
    {
        return _letter;
    }
}

To override BuildNewsLetterHTML it must be marked virtual.

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