如何将moq添加到工作的mstest单元测试中

时间:2011-11-23 20:55:55

标签: moq mstest

我正在使用MSTest编写单元测试,但我的任务是将moq添加到单元测试中。我理解,如果进行集成测试,其中通常调用文件系统,数据库,那么模拟基本上允许测试而不实际进行那些“真正的”调用。我环顾四周,只是需要一些帮助。

我从一些我发现的基本实用程序开始,并开始使用Asserts对它们进行一些基本测试。但是,我需要将它带到下一步并利用MOQ。

以下是我正在测试的方法:

    public static bool IsStringEmptyOrNull(string strValue)
    {
        if(null != strValue)
        {
            strValue = strValue.Trim().ToLower();
            return (string.Empty == strValue || "undefined" == strValue);
        }
        return true;
    }

然后我有一个看起来像这样的测试:

  using System;
  using System.Text;
  using System.Collections.Generic;
  using System.Linq;
  using Microsoft.VisualStudio.TestTools.UnitTesting;
  using Company.W.Utilities;


namespace CESUtilities.Tests
{
[TestClass]
public class When_string_is_empty_or_null
{
    private string empty;
    private string isnull;
    private bool expected;

    [TestInitialize()]
    public void TestInitialize()
    {
        empty = "";
        isnull = null;
        expected = true;
    }

    [TestMethod]
    public void when_string_is_empty()
    {

        bool actual = Util.IsStringEmptyOrNull(empty);   
        Assert.AreEqual(expected, actual);
    }

    [TestMethod]
    public void when_string_is_null()
    {
        bool actual = Util.IsStringEmptyOrNull(isnull);
        Assert.AreEqual(expected, actual);
    }



    [TestCleanup()]
    public void TestCleanup()
    {

    }


  }
}

1 个答案:

答案 0 :(得分:12)

首先,正如您所提到的,您可以使用模拟替换依赖项。您发布的代码在依赖性方面并不多,但让我们假装它。

您正在测试方法IsStringEmptyOrNull。

让我们假设该方法属于一个名为Foo的类(我只是制作东西)。我也会改变方法。

public class Foo
{
    private IBar _bar;

    public Foo(IBar bar)
    {
        _bar = bar; 
    }   

    public static bool IsStringEmptyOrNull(string strValue)
    {
        // dependency is called here
        var readValue = bar.ReadFromFileSystemOrDatabase();

        if(null != strValue 
           && readValue == 1)
        {
            strValue = strValue.Trim().ToLower();
            return (string.Empty == strValue || "undefined" == strValue);
        }
        return true;
    }
}

在这里你可以看到类Foo有一个在构造函数中注入的Bar。此外,它在您的方法中使用。如果您不希望测试实际调用此方法:

  • 因为它调用了db
  • 因为它调用文件系统
  • 您希望将代码与方法隔离,与其他外部代码隔离(在本例中为ReadFromFileSystemOrDatabase()

然后,您可以使用模拟来完成此操作。 您将如何做到这一点:

// create your mock object
var mockBar = new Mock<IBar>();

// setup a method to return a result when the mock object is called
// notice the return value, which is 1
mockBar.Setup(mock => mock.ReadFromFileSystemOrDatabase()).Returns(1);

// you can then inject the mock object in the object you are testing
var foo = new Foo(mockBar.Object);

当您的测试运行时,将会向该类提供依赖项的模拟版本(在本例中为Bar)。

当方法将对此模拟进行调用时,如果您有 Setup 方法返回值,它将返回此值。

通过这种方式,您可以抽象出依赖关系来集中测试或模拟对数据库或文件系统的调用。

至于你提到的确切例子,没有什么可以嘲笑的。您的确切示例不适用于使用模拟。

模拟不是你为所有测试做的事情。