【问题标题】:Mocking a method in the same interface with MOQ在与 MOQ 相同的接口中模拟方法
【发布时间】:2010-11-22 07:13:15
【问题描述】:

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

这是我的设置:

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 上失败,因为实际为空。你们中有人知道为什么实际为空吗?

提前致谢。

【问题讨论】:

    标签: c# mocking moq


    【解决方案1】:

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

    我建议您在这种情况下使用extract and override pattern,因为您希望在具有被测方法的同一类的方法中造成虚假实现。

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

    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,它必须被标记为虚拟。

    【讨论】:

    • 感谢您的回复。我试过你的方法,效果很好!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多