C# 滥用最小起订量测试if条件

C# 滥用最小起订量测试if条件,c#,unit-testing,moq,C#,Unit Testing,Moq,考虑到以下类别: public class test { public void start() { if (true) called(); } internal protected virtual void called() { } } 我想测试if(true)。我最初的想法是使用Moq来验证调用了called()。我最后做了这个测试: [TestFixture] public partial cla

考虑到以下类别:

public class test
{
    public void start()
    {
        if (true)
            called();
    }

    internal protected virtual void called()
    {

    }
}
我想测试
if(true)
。我最初的想法是使用Moq来验证调用了
called()
。我最后做了这个测试:

[TestFixture]
public partial class TestMethodInvocation
{
    [Test]
    public void TestWithMoqVerify()
    {
        var mock = new Mock<test>() {CallBase = true};
        mock.Object.start();
        mock.Verify(t => t.called());
    }
}

这两种方法都可以工作,但是Moq实现实际上是测试代码量的一半,因为我不需要创建子类。像这样使用Moq是非常糟糕的,还是我应该使用另一个框架来做这种测试?或者这是我的代码设计中出现问题的结果?

是否应该为调用验证编写测试存在一些争议,我试图避开它们,我宁愿测试外部行为。您可以测试一些东西,看看是否达到了预期的结果,而无需深入内部。当然,这并不总是可能的

说到这里,我想给大家举个例子(最好的办法)。假设我们有一个名为
Greeter
的类,它应该向所有订户发送一条恼人的短信。现在,假设为了发送短信,您已经在其他地方编写了一些其他的基础结构代码(已经测试过了)。假设此代码将是一个名为
IMessageService
的接口的实现(如果我的示例很糟糕,那么很抱歉):

另外,假设您有一个
SubscriberRepository
,它将获得所有StackOverflow订阅服务器。比如:

public interface ISubscriberRepository
{
    IEnumerable<Subscriber> GetStackOverflowSubscribers();
}
您可以看到,它实际上是在使用
IMessageService
发送短信。此时,您希望(可能)测试调用
SendSMS()
的次数是否为
x
。在这种情况下,次数应与StackOverflow订阅服务器的数量相同。因此,您的测试将如下所示:

[Test]
public void SendGreetingToStackOverflow_CallsIMessageServiceSendSMSTwoTimes()
{
    var mockMessageService = new Mock<IMessageService>();
    var mockSubscriberRepo = new Mock<ISubscriberRepository>();

    // we will mock the repo and pretend that it returns 2 subscibers
    mockSubscriberRepo
        .Setup(x => x.GetStackOverflowSubscribers())
        .Returns(new List<Subscriber>() {new Subscriber(), new Subscriber()});

    // this is the one we're testing, all dependencies are fake
    var greeter = new Greeter(mockMessageService.Object, mockSubscriberRepo.Object);

    greeter.SendGreetingToStackOverflow();

    // was it called 2 times (for each subscriber) ?
    mockMessageService.Verify(
        x => x.SendSMS("Hello World!"),
        Times.Exactly(2));
}
[TestFixture]
public partial class TestMethodInvocation
{
  [Test]
  public void TestWithMoqVerify()
  {
    var callableMock = new Mock<Callable>();
    var test = new Test(callableMock);
    test.Start();
    callableMock.Verify(t => t.Called());
  }
}
[测试]
public void SendGreetingToStackOverflow_CallsIMessageServiceSendSMSTwoTimes()
{
var mockMessageService=new Mock();
var mockSubscriberRepo=new Mock();
//我们将模拟回购协议,并假装它返回2个子客户
莫克贝雷波酒店
.Setup(x=>x.GetStackOverflowSubscribers())
.Returns(new List(){new Subscriber(),new Subscriber()});
//这是我们正在测试的,所有依赖项都是假的
var greeter=新的greeter(mockMessageService.Object、mockSubscriberRepo.Object);
greeter.SendGreetingToStackOverflow();
//是否呼叫了2次(每个用户)?
mockMessageService.Verify(
x=>x.SendSMS(“你好,世界!”),
正是(2));
}
再次抱歉,这可能不是最好的例子,但这是漫长的一天,这是我能想到的最好的例子:)


我希望这会有所帮助。

是否应该编写调用验证测试存在一些争议,我试图避开它们,我宁愿测试外部行为。您可以测试一些东西,看看是否达到了预期的结果,而无需深入内部。当然,这并不总是可能的

说到这里,我想给大家举个例子(最好的办法)。假设我们有一个名为
Greeter
的类,它应该向所有订户发送一条恼人的短信。现在,假设为了发送短信,您已经在其他地方编写了一些其他的基础结构代码(已经测试过了)。假设此代码将是一个名为
IMessageService
的接口的实现(如果我的示例很糟糕,那么很抱歉):

另外,假设您有一个
SubscriberRepository
,它将获得所有StackOverflow订阅服务器。比如:

public interface ISubscriberRepository
{
    IEnumerable<Subscriber> GetStackOverflowSubscribers();
}
您可以看到,它实际上是在使用
IMessageService
发送短信。此时,您希望(可能)测试调用
SendSMS()
的次数是否为
x
。在这种情况下,次数应与StackOverflow订阅服务器的数量相同。因此,您的测试将如下所示:

[Test]
public void SendGreetingToStackOverflow_CallsIMessageServiceSendSMSTwoTimes()
{
    var mockMessageService = new Mock<IMessageService>();
    var mockSubscriberRepo = new Mock<ISubscriberRepository>();

    // we will mock the repo and pretend that it returns 2 subscibers
    mockSubscriberRepo
        .Setup(x => x.GetStackOverflowSubscribers())
        .Returns(new List<Subscriber>() {new Subscriber(), new Subscriber()});

    // this is the one we're testing, all dependencies are fake
    var greeter = new Greeter(mockMessageService.Object, mockSubscriberRepo.Object);

    greeter.SendGreetingToStackOverflow();

    // was it called 2 times (for each subscriber) ?
    mockMessageService.Verify(
        x => x.SendSMS("Hello World!"),
        Times.Exactly(2));
}
[TestFixture]
public partial class TestMethodInvocation
{
  [Test]
  public void TestWithMoqVerify()
  {
    var callableMock = new Mock<Callable>();
    var test = new Test(callableMock);
    test.Start();
    callableMock.Verify(t => t.Called());
  }
}
[测试]
public void SendGreetingToStackOverflow_CallsIMessageServiceSendSMSTwoTimes()
{
var mockMessageService=new Mock();
var mockSubscriberRepo=new Mock();
//我们将模拟回购协议,并假装它返回2个子客户
莫克贝雷波酒店
.Setup(x=>x.GetStackOverflowSubscribers())
.Returns(new List(){new Subscriber(),new Subscriber()});
//这是我们正在测试的,所有依赖项都是假的
var greeter=新的greeter(mockMessageService.Object、mockSubscriberRepo.Object);
greeter.SendGreetingToStackOverflow();
//是否呼叫了2次(每个用户)?
mockMessageService.Verify(
x=>x.SendSMS(“你好,世界!”),
正是(2));
}
再次抱歉,这可能不是最好的例子,但这是漫长的一天,这是我能想到的最好的例子:)


我希望它能有所帮助。

一个最简单的例子是,尽可能接近您想要做的事情:

interface Callable
{
  void Called();
}

class Test
{
  public Test(Callable x)
  {
    this.callable = callable;
  }

  public void Start()
  {
    if (true)
      callable.Called();
  }

  private Callable callable;
}
然后测试将如下所示:

[Test]
public void SendGreetingToStackOverflow_CallsIMessageServiceSendSMSTwoTimes()
{
    var mockMessageService = new Mock<IMessageService>();
    var mockSubscriberRepo = new Mock<ISubscriberRepository>();

    // we will mock the repo and pretend that it returns 2 subscibers
    mockSubscriberRepo
        .Setup(x => x.GetStackOverflowSubscribers())
        .Returns(new List<Subscriber>() {new Subscriber(), new Subscriber()});

    // this is the one we're testing, all dependencies are fake
    var greeter = new Greeter(mockMessageService.Object, mockSubscriberRepo.Object);

    greeter.SendGreetingToStackOverflow();

    // was it called 2 times (for each subscriber) ?
    mockMessageService.Verify(
        x => x.SendSMS("Hello World!"),
        Times.Exactly(2));
}
[TestFixture]
public partial class TestMethodInvocation
{
  [Test]
  public void TestWithMoqVerify()
  {
    var callableMock = new Mock<Callable>();
    var test = new Test(callableMock);
    test.Start();
    callableMock.Verify(t => t.Called());
  }
}
[TestFixture]
公共部分类TestMethodInvocation
{
[测试]
使用moqverify()的公共无效测试
{
var callableMock=new Mock();
var测试=新测试(callableMock);
test.Start();
callableMock.Verify(t=>t.Called());
}
}
重新表述我的评论:


您不应该测试类的内部-测试外部行为。

一个有一定意义的最小示例,尽可能接近您要做的事情:

interface Callable
{
  void Called();
}

class Test
{
  public Test(Callable x)
  {
    this.callable = callable;
  }

  public void Start()
  {
    if (true)
      callable.Called();
  }

  private Callable callable;
}
然后测试将如下所示:

[Test]
public void SendGreetingToStackOverflow_CallsIMessageServiceSendSMSTwoTimes()
{
    var mockMessageService = new Mock<IMessageService>();
    var mockSubscriberRepo = new Mock<ISubscriberRepository>();

    // we will mock the repo and pretend that it returns 2 subscibers
    mockSubscriberRepo
        .Setup(x => x.GetStackOverflowSubscribers())
        .Returns(new List<Subscriber>() {new Subscriber(), new Subscriber()});

    // this is the one we're testing, all dependencies are fake
    var greeter = new Greeter(mockMessageService.Object, mockSubscriberRepo.Object);

    greeter.SendGreetingToStackOverflow();

    // was it called 2 times (for each subscriber) ?
    mockMessageService.Verify(
        x => x.SendSMS("Hello World!"),
        Times.Exactly(2));
}
[TestFixture]
public partial class TestMethodInvocation
{
  [Test]
  public void TestWithMoqVerify()
  {
    var callableMock = new Mock<Callable>();
    var test = new Test(callableMock);
    test.Start();
    callableMock.Verify(t => t.Called());
  }
}
[TestFixture]
公共部分类TestMethodInvocation
{
[测试]
使用moqverify()的公共无效测试
{
var callableMock=new Mock();
var测试=新测试(callableMock);
test.Start();
callableMock.Verify(t=>t.Called());
}
}
重新表述我的评论:


您不应该测试类的内部-测试外部行为。

我认为您真正要问的问题是如何测试名为的方法是否在
测试中执行