如何使用moq模拟方法调用

时间:2017-04-27 05:22:10

标签: c# mocking nunit moq

我的单位测试方法如下

[Test]
public void TrackPublicationChangesOnCDSTest()
{
    //Arrange
    // objDiskDeliveryBO = new DiskDeliveryBO();            

    //Act
    var actualResult = objDiskDeliveryBO.TrackPublicationChangesOnCDS();

    //Assert 
    var expectedZipName = 0;
    Assert.AreEqual(expectedZipName, actualResult);
}

BO中的实际方法TrackPublicationChangesOnCDS如下

public int TrackPublicationChangesOnCDS()
{

    var resultFlag = -1;

    try
    {

        string pubUpdateFileCDSPath = CommonCalls.PubUpdateFileCDSPath;
        string pubUpdateFileLocalPath = CommonCalls.PubUpdateFileLocalPath;


        if (File.Exists(pubUpdateFileCDSPath))
            File.Copy(pubUpdateFileCDSPath, pubUpdateFileLocalPath, true);

        if (File.Exists(pubUpdateFileLocalPath))
        {

            string[] pubRecords = File.ReadAllLines(pubUpdateFileLocalPath);

            var pubRecordsExceptToday = pubRecords.Where(p => !p.Trim().EndsWith(DateTime.Now.ToString("dd/MM/yy"))).ToList();

            resultFlag = new DiskDeliveryDAO().TrackPublicationChangesOnCDS(pubRecordsExceptToday);

            File.WriteAllText(pubUpdateFileLocalPath, string.Empty);

            string[] pubRecordsCDS = File.ReadAllLines(pubUpdateFileCDSPath);
            var pubRecordsTodayCDS = pubRecordsCDS.Where(p => p.Trim().EndsWith(DateTime.Now.ToString("dd/MM/yy"))).ToList();
            File.WriteAllLines(pubUpdateFileCDSPath, pubRecordsTodayCDS);

        }

        return resultFlag;
    }
    catch (Exception)
    {

        return -1;
    }

}

我想模拟方法调用  DiskDeliveryDAO().TrackPublicationChangesOnCDS(pubRecordsExceptToday);

我怎样才能做到这一点?我没有在线获得足够的例子。我正在使用Moq库。有人可以帮忙吗?

3 个答案:

答案 0 :(得分:2)

当前代码与实现问题紧密耦合,使其易于单独测试。

检查测试中的方法揭示了以下被抽象的依赖

public interface ICommonCalls {
    string PubUpdateFileCDSPath { get; }
    string PubUpdateFileLocalPath { get; }
}

public interface IDiskDeliveryDAO {
    int TrackPublicationChangesOnCDS(List<string> pubRecordsExceptToday);
}

public interface IFileSystem {
    bool Exists(string path);
    void Copy(string sourceFilePath, string destinationFilePath, bool overwrite);
    string[] ReadAllLines(string path);
    void WriteAllText(string path, string contents);
    void WriteAllLines(string path, IEnumerable<string> contents);
}

他们各自的实现将在生产中包装/实现所需的功能。

抽象现在允许对被测方法进行重构,如下所示。

public class DiskDeliveryBO {
    readonly ICommonCalls CommonCalls;
    readonly IDiskDeliveryDAO diskDeliveryDAO;
    readonly IFileSystem File;

    public DiskDeliveryBO(ICommonCalls CommonCalls, IDiskDeliveryDAO diskDeliveryDAO, IFileSystem File) {
        this.CommonCalls = CommonCalls;
        this.diskDeliveryDAO = diskDeliveryDAO;
        this.File = File;
    }

    public int TrackPublicationChangesOnCDS() {

        var resultFlag = -1;

        try {

            string pubUpdateFileCDSPath = CommonCalls.PubUpdateFileCDSPath;
            string pubUpdateFileLocalPath = CommonCalls.PubUpdateFileLocalPath;


            if (File.Exists(pubUpdateFileCDSPath))
                File.Copy(pubUpdateFileCDSPath, pubUpdateFileLocalPath, true);

            if (File.Exists(pubUpdateFileLocalPath)) {

                string[] pubRecords = File.ReadAllLines(pubUpdateFileLocalPath);

                var pubRecordsExceptToday = pubRecords.Where(p => !p.Trim().EndsWith(DateTime.Now.ToString("dd/MM/yy"))).ToList();

                resultFlag = diskDeliveryDAO.TrackPublicationChangesOnCDS(pubRecordsExceptToday);

                File.WriteAllText(pubUpdateFileLocalPath, string.Empty);

                string[] pubRecordsCDS = File.ReadAllLines(pubUpdateFileCDSPath);
                var pubRecordsTodayCDS = pubRecordsCDS.Where(p => p.Trim().EndsWith(DateTime.Now.ToString("dd/MM/yy"))).ToList();
                File.WriteAllLines(pubUpdateFileCDSPath, pubRecordsTodayCDS);
            }

            return resultFlag;
        } catch (Exception) {

            return -1;
        }
    }
}

注意除了改变new DiskDeliveryDAO()与注入依赖关系的紧密耦合之外,方法本身实际上没有多少变化。

现在,类更灵活,可以在完全控制依赖关系及其行为的情况下进行单独测试。

public class DiskDeliveryBOTests {
    [Test]
    public void TrackPublicationChangesOnCDSTest() {
        //Arrange
        var expected = 0;
        var commonMock = new Mock<ICommonCalls>();
        //...Setup commonMock desired behavior

        var daoMock = new Mock<IDiskDeliveryDAO>();
        //...Setup daoMock desired behavior
        daoMock
            .Setup(_ => _.TrackPublicationChangesOnCDS(It.IsAny<List<string>>())
            .Returns(expected);

        var fileMock = new Mock<IFileSystem>();
        //...Setup fileMock desired behavior

        var objDiskDeliveryBO = new DiskDeliveryBO(commonMock.Object, daoMock.Object, fileMock.Object);

        //Act
        var actualResult = objDiskDeliveryBO.TrackPublicationChangesOnCDS();

        //Assert             
        Assert.AreEqual(expected, actualResult);
    }
}

检查Moq Quickstart以获取有关如何在模拟上设置所需行为的更多信息。

答案 1 :(得分:1)

使用moq模拟DiskDeliveryDAO()。TrackPublicationChangesOnCDS(pubRecordsExceptToday)是不可能的,因为它使用具体类直接创建对象。只有当我们有具体的类实现一个接口并且DiskDeliveryDAO对象应该通过DiskDeliveryBO的构造函数注入时才有可能。

答案 2 :(得分:0)

var mockDeliveryDao = new Mock<DiskDeliveryDAO>();

mockDeliveryDao.Setup(o=>o.TrackPublicationChangesOnCDS(It.IsAny<List<string>>()).Returns(1);//or whatever flag you want

现在您需要将deliveryDao作为参数传递给构造函数。使用依赖注入而不是在代码中创建新的DeliveryDao()对象。

这样你的代码就会读到:

    resultFlag = _diskDeliveryDao.TrackPublicationChangesOnCDS(pubRecordsExceptToday);

虽然您的构造函数将设置_diskDeliveryDao成员变量。