Moq-检查具体类的方法调用

dro*_*gon 4 c# nunit unit-testing moq

这是我要执行的操作的一个非常简单的示例:

public class Bar
{
    public void SomeMethod(string param)
    {
        //whatever
    }
}

public interface IBarRepository
{
    List<Bar> GetBarsFromStore();
}

public class FooService
{
    private readonly IBarRepository _barRepository;

    public FooService(IBarRepository barRepository)
    {
        _barRepository = barRepository;
    }

    public List<Bar> GetBars()
    {
        var bars = _barRepository.GetBarsFromStore();
        foreach (var bar in bars)
        {
            bar.SomeMethod("someValue");
        }
        return bars;
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的测试中,我正在模拟IBarRepository以返回在单元测试中定义的具体List,并将该模拟的存储库实例传递给FooService构造函数。

我想在FooService方法GetBars中验证从存储库返回的每个Bar都调用了SomeMethod。我正在使用起订量。有什么方法可以在不嘲笑返回的Bars列表的情况下(即使可能的话)并且不必在Bar中放置一些hacky标志(yuck)?

我正在跟踪DDD书中的示例,但我开始认为它闻起来是因为我在测试实现方面遇到了挑战。

Eri*_*ich 5

修订...通过:

public class Bar
{
    public virtual void SomeMethod(string param)
    {
        //whatever
    }
}

public interface IBarRepository
{
    List<Bar> GetBarsFromStore();
}

public class FooService
{
    private readonly IBarRepository _barRepository;

    public FooService(IBarRepository barRepository)
    {
        _barRepository = barRepository;
    }

    public List<Bar> GetBars()
    {
        var bars = _barRepository.GetBarsFromStore();
        foreach (var bar in bars)
        {
            bar.SomeMethod("someValue");
        }
        return bars;
    }
}

[TestMethod]
public void Verify_All_Bars_Called()
{
    var myBarStub = new Mock<Bar>();
    var mySecondBarStub = new Mock<Bar>();

    var myBarList = new List<Bar>() { myBarStub.Object, mySecondBarStub.Object };
    var myStub = new Mock<IBarRepository>();
    myStub.Setup(repos => repos.GetBarsFromStore()).Returns(myBarList);
    var myService = new FooService(myStub.Object);
    myService.GetBars();

    myBarStub.Verify(bar => bar.SomeMethod(It.IsAny<string>()), Times.Once());
    mySecondBarStub.Verify(bar => bar.SomeMethod(It.IsAny<string>()), Times.Once());
}
Run Code Online (Sandbox Code Playgroud)

请注意,对Bar类的更改很小(SomeMethod()是虚拟的)。更改,但不涉及标志... :)

现在,就更广泛的设计而言,您的工具栏上正在进行一些更改(无论“ SomeMethod()”实际上是做什么的)。最好的办法可能是验证此突变是否发生在从FooService.GetBars()返回的每个Bar上。也就是说,将您的存储库存根设置为返回一些小节,然后验证SomeMethod()所执行的任何更改都已发生。毕竟,您控制着将要返回的柱线,因此您可以设置它们的pre-SomeMethod()状态,然后检查其post-SomeMethod()状态。