检查调用某些方法应该属于单元测试

时间:2014-06-26 08:00:07

标签: c# asp.net unit-testing

我试图跟踪测试行为而不是方法(这是我最初在做的事情)。就像我正在测试我从服务器刷新项目的功能。

基本上是在 RefreshItems ()方法中完成的。在这种方法中,我可以调用其他服务的其他方法,比如你可以说 NetworkService (用于网络请求)。

由于RefreshItems的实现可能会发生变化,或者它可能没有调用NetworkService的某些特定方法。

我的 UnitTests 是否应包含测试以检查是否已调用NetworkService方法?

2 个答案:

答案 0 :(得分:0)

我会检查是否已拨打所有必要的电话。在测试RefreshItems时,模拟依赖服务(如NetworkService)并验证调用。

修改

假设您拥有MyService的界面和实现。

public interface IMyService
{
    IEnumerable<string> Get();
    void SuperImportantMethod();
}

public class MyService : IMyService
{
    public IEnumerable<string> Get()
    {
        SuperImportantMethod();
        return new string[] { string.Empty };
    }

    public virtual void SuperImportantMethod()
    {
        // and secret!
    }
}

然后使用此服务的MyClass,如:

public class MyClass
{
    public MyClass()
    {}

    public MyClass(IMyService service)
    {
        Service = service;
    }
    public void RefreshItems()
    {
        Items = Service.Get();
    }

    public IMyService Service { get; set; }

    public IEnumerable<string> Items { get; set; }
}

然后,您可以测试与服务隔离的MyClass RefreshItems方法。

[TestMethod]
public void RefreshItemsTest()
{
    var expected = new string[] {"my", "items", "here"};

    var myClass = new MyClass();
    var mock = new Mock<IMyService>();

    mock.Setup(service => service.Get()).Returns(expected);
    myClass.Service = mock.Object;

    myClass.RefreshItems();
    Assert.IsTrue(expected.SequenceEqual(myClass.Items));
}

在测试MyService时,您可以确保每次服务“获取”某些内容时都会调用SuperImportantMethod

[TestClass]
public class MyServiceTests
{
    [TestMethod]
    public void GetTest()
    {
        var mock = new Mock<MyService>();
        var service = mock.Object;

        service.Get();
        mock.Verify(s => s.SuperImportantMethod(), Times.Once);
    }
}

答案 1 :(得分:0)

NetworkService注入界面。它可以被称为INetworkService,但IItemsService可能会出现问题:

public interface IItemsService
{
    Items GetAllItems(); //or whatever you need
}

然后你有两个选择:

模拟并验证

为该接口注入一个模拟并验证是否调用了正确的调用,但正如您所说,这将测试实现而不是行为。

var itemsService = new Mock<IItemsService>(); //Moq for example
var testObject = new ClassUnderTest(itemsService.Object);
testObject.RefreshItems();
itemsService.Verify(e => e.GetAllItems(), Times.Once); //verify the calls to the moq

<强>存根

创建一个返回固定数据的IItemsService的Stub实现。然后Assert您正在测试的班级的新状态。

var itemsService = new StubItemsService();
var testObject = new ClassUnderTest(itemsService);
testObject.RefreshItems();
Assert.AreEqual(1, testObject.Items); //some assert on the testObject

请注意,您也可以使用Moq进行存根,而不是创建存根类:

var itemsService = new Mock<IItemsService>();
itemsService.Setup(e => e.GetItems()).Returns(/*whatever*/);
var testObject = new ClassUnderTest(itemsService.Object);
testObject.RefreshItems();
Assert.AreEqual(1, testObject.Items); //some assert on the testObject