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

Ger*_*ard 4 c# moq mocking

我有一个服务方法,我想测试.该方法在同一个类中调用另一个方法.这个方法已经过测试,所以我想模仿那个方法.

这是我的设置:

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);
}
Run Code Online (Sandbox Code Playgroud)

这是我正在使用的测试:

[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);
}
Run Code Online (Sandbox Code Playgroud)

现在的问题是我正在模拟的函数:BuildNewsLetterHTML返回null而不是它应该返回的内容.

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

public string CreateNewsLetter(NewsLetter newsLetter)
{
    var newsletterHTML = BuildNewsLetterHTML(newsLetter);
    return newsletterHTML;
}
Run Code Online (Sandbox Code Playgroud)

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

提前致谢.

CRi*_*ice 6

似乎问题是你正在调用Mock<T>'s尚未设置的CreateNewsLetter方法,这似乎也是你正在测试的方法.你不应该对你的假货进行测试,它们应该替代生产代码以帮助测试其他代码.

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

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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