简体   繁体   English

使用MOQ在同一接口中模拟方法

[英]Mocking a method in the same interface with MOQ

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. 现在的问题是我正在模拟的函数:BuildNewsLetterHTML返回null而不是它应该返回的内容。

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. Assert.AreEqual上的测试失败,因为实际为null。 Any of you have any idea why actual is null? 你们中的任何人都知道为什么实际为空?

Thanks in advance. 提前致谢。

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. 似乎问题是你正在调用Mock<T>'s CreateNewsLetter方法,该方法尚未设置,并且似乎也是您正在测试的方法。 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. Moq在某些情况下很棒,但我不认为在情况需要时使用小的可读存根有什么问题。

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. 要覆盖BuildNewsLetterHTML,必须将其标记为虚拟。

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

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