1

I am pretty new to MOQ and I am in learning right now. I got task that I need to write unit test But I am getting the below error which I couldn't able to find. Please anyone help me with this. Also please review the code and give me some advises if my testcase needs changes.

Expection: IAcronisService.GetActivitiesFromDate("mygroup", 5/24/2016 8:33:34 PM) invocation failed with mock behavior Strict.....

for Save method(I have commented at save method where the exception has been thrown)

Process method calls save method

public int Process()
{
    AcronisService = AcronisSvcManager.Get(ClientFactory, DataProviderFactory, LogAdapter);

    DataObject backupGroupsDO = GetListOfAllCurrentGroups();

    int activitiesSavedCount = Save(backupGroupsDO);
    return activitiesSavedCount;
}

When I debug I also have seen the below line when I mouse over at first line on above process method. I thought service object is not calling/mocking. Is this anything to do with above exception? Please suggest some changes.

(IAcronisServiceProxy)AcronisService).AcronisURL threw a exception of type MOQ.MockException.

Save Method

private int Save(DataObject backupGroupsDO)
{
    int count = 0;

    foreach (DataRecord dr in backupGroupsDO.DataRecord)
    {
        BackupGroup backupGroup = new BackupGroup(dr);

        // Get all activities for each group
        AcronisClient.DataModel.Activity.ActivitiesResponse acronisActivities;
        if (backupGroup.LastActivityDate == null)
        {
            // Get all activities for each group
            ***//Got Exception at this line***
            acronisActivities = AcronisService.GetActivitiesFromDate(backupGroup.GroupName, DateTime.Now.AddDays(-90)); 
        }
        else
        {
            acronisActivities = AcronisService.GetActivitiesFromDate(backupGroup.GroupName, backupGroup.LastActivityDate);
        }



        if (acronisActivities == null || acronisActivities.Activities == null)
        {
            // Stop processing b/c might be an issue with the connection to Acronis
            LogAdapter.LogError(KCBLog.Main, "Stopped processing activities, possible Acronis connection issue with getting Activities");
            return -1;
        }
        var lastBackUpActivity = acronisActivities.Activities.OrderByDescending(z => z.StartTime).FirstOrDefault();

        List<string> lastSuccessfulActivities = new List<string>();
        List<string> lastActivities = new List<string>();

        foreach (var acronisActivity in acronisActivities.Activities)
        {

            Kaseya.KCB.Common.DataModels.AcronisActivity activity = new AcronisActivity();
            activity.BackupPlanId = acronisActivity.BackupPlanId;
            activity.BytesProcessed = acronisActivity.BytesProcessed;
            activity.BytesSaved = acronisActivity.BytesSaved;


            activity.Cause = acronisActivity.CompletionResult == null ? null : acronisActivity.CompletionResult.Cause;
            activity.Reason = acronisActivity.CompletionResult == null ? null : acronisActivity.CompletionResult.Reason;
            activity.Effect = acronisActivity.CompletionResult == null ? null : acronisActivity.CompletionResult.Effect;

            activity.DateCreated = DateTime.Now;

            activity.FinishTime = acronisActivity.FinishTime;
            activity.GroupId = backupGroup.Id;
            activity.Id = acronisActivity.Id;
            activity.InitiatedBy = acronisActivity.InitiatedBy;
            activity.InstanceId = acronisActivity.InstanceId;
            activity.IsRootActivity = (bool)acronisActivity.IsRootActivity;
            activity.ParentActivityId = acronisActivity.ParentActivityId;
            activity.PartitionId = PartitionId;
            activity.StartTime = acronisActivity.StartTime;
            activity.State = acronisActivity.State;
            activity.Status = acronisActivity.Status;
            activity.Title = acronisActivity.Title;
            activity.UpdateTime = acronisActivity.UpdateTime;

            AcronisActivityDataProvider.AddUpdateAcronisActivity(activity);

            AcronisClient.DataModel.Activity.Activity lastSuccessfulActivity = acronisActivities.Activities.Where(z => z.Status == "ok" && z.Title.Contains("Running backup plan") && z.InstanceId==acronisActivity.InstanceId).OrderByDescending(z => z.FinishTime).FirstOrDefault();
            var lastActivity = acronisActivities.Activities.Where(z => z.Title.Contains("Running backup plan") && z.InstanceId == acronisActivity.InstanceId).OrderByDescending(z => z.FinishTime).FirstOrDefault();


            if (!string.IsNullOrEmpty(acronisActivity.InstanceId))
            {
                DataRecord assetDR = AssetDataProvider.GetByInstanceId(acronisActivity.InstanceId, PartitionId);
                if (assetDR != null)
                {
                    var assetId = assetDR.FindValue<string>("id", "");

                    if (lastSuccessfulActivity != null && !lastSuccessfulActivities.Contains(acronisActivity.InstanceId))
                    {
                        AssetDataProvider.UpdateLastSuccessfulActivityId(assetId, lastSuccessfulActivity.ParentActivityId);
                        lastSuccessfulActivities.Add(acronisActivity.InstanceId);
                    }
                    if (lastActivity != null && !lastActivities.Contains(acronisActivity.InstanceId))
                    {
                        AssetDataProvider.UpdateLastActivityId(assetId, lastActivity.ParentActivityId);
                        lastActivities.Add(acronisActivity.InstanceId);
                    }
                }
            }
            count++;
        }

        if (acronisActivities.Activities != null && acronisActivities.Activities.Count>0)
        {
            //backupGroup.LastActivityDate = lastBackUpActivity.StartTime;
            BackupGroupDataProvider.UpdateLastBackupGroupActivityDate(backupGroup.Id, lastBackUpActivity.StartTime);
        }
    }

    return count;
}

Test Method I have writtern,

public void Test()
{
    string groupName = "mygroup";
    string mybackupAccountName = "mybackupaccount";
    decimal PartitionId = 9m;
    DateTime lastActivityDate = DateTime.Parse("2016-08-14T20:47:05");
    string instanceId = "utinstanceId";
    string assetId = "123";


    DataRecord asset = new DataRecord();
    asset.AddField("id", 123);

    DataObject backupGroupsDO = new DataObject();
    DataRecord groupDataRecord = new DataRecord();
    groupDataRecord.AddField("id", 123);
    groupDataRecord.AddField("partitionId", PartitionId);
    groupDataRecord.AddField("groupName", groupName);

    //groupDataRecord.AddField("lastActivityDate", lastActivityDate);

    groupDataRecord.AddField("backupAccountName", mybackupAccountName);
    backupGroupsDO.DataRecord.Add(groupDataRecord);

    AcronisActivity acronisActivity = new AcronisActivity();
    acronisActivity.BackupPlanId = "utBackupPlanId";

    ActivitiesResponse activitiesResponse = new ActivitiesResponse();
    AcronisClient.DataModel.Activity.Activity activity = new AcronisClient.DataModel.Activity.Activity();
    activity.BackupPlanId = "utackupPlanId";
    activity.BytesProcessed = 124674;
    activity.BytesSaved = 06446;
    activity.CompletionResult = new CompletionResult()
    {
        Cause = "utCause",
        Reason = "utReason",
        Effect = "utEffect"
    };
    activity.FinishTime = DateTime.Parse("2016-08-14T20:47:04");
    activity.Id = "utId";
    activity.InitiatedBy = "utInitiatedBy";
    activity.InstanceId = "utInstanceId";
    activity.IsRootActivity = true;
    activity.ParentActivityId = "utParentActivityId";
    activity.StartTime = DateTime.Parse("2016-08-14T20:47:02");
    activity.State = "utState";
    activity.Status = "utStatus";
    activity.Title = "utTitle";
    activity.UpdateTime = DateTime.Parse("2016-08-14T20:47:03");

    activitiesResponse.Activities = new List<AcronisClient.DataModel.Activity.Activity>();
    activitiesResponse.Activities.Add(activity);

    var moqFactory = new MockRepository(MockBehavior.Strict);

    var moqDataProviderFactory = moqFactory.Create<IDataProviderFactory>();
    var moqDataProvider = moqFactory.Create<IDataProvider>();
    var moqLogAdapter = moqFactory.Create<ILogAdapter>();
    var moqAcronisServiceManager = moqFactory.Create<IAcronisServiceManager>();
    var moqAcronisService = moqFactory.Create<IAcronisService>();
    var moqAssetDataProvider = moqFactory.Create<IAssetDataProvider>();
    var moqAcronisActivityDataProvider = moqFactory.Create<IAcronisActivityDataProvider>();
    var moqBackupGroupDataProvider = moqFactory.Create<IBackupGroupDataProvider>();


    Credential MSPCredential = new Credential();

    moqDataProviderFactory.Setup(m => m.BackupGroupDataProvider.GetBackupGroups()).Returns(backupGroupsDO);

    moqAcronisServiceManager.Setup(m => m.Get(It.IsAny<IRestClientFactory>(), It.IsAny<IDataProviderFactory>(), It.IsAny<ILogAdapter>(), "")).Returns(moqAcronisService.Object);

    moqDataProvider.Setup(m => m.VerifyPartitionId(ref PartitionId));
    moqDataProvider.Setup(m => m.ExecuteNonQuery(It.IsAny<AddUpdateAcronisActivity>())).Returns(1);
    moqAcronisService.Setup(m => m.GetActivitiesFromDate(groupName, lastActivityDate)).Returns(activitiesResponse);
    moqAcronisActivityDataProvider.Setup(m => m.AddUpdateAcronisActivity(acronisActivity));
    moqAssetDataProvider.Setup(m => m.GetByInstanceId(instanceId, PartitionId,1)).Returns(asset);
    moqAssetDataProvider.Setup(m => m.UpdateLastActivityId(assetId, activity.ParentActivityId));
    moqAssetDataProvider.Setup(m => m.UpdateLastSuccessfulActivityId(assetId, activity.ParentActivityId));
    moqBackupGroupDataProvider.Setup(m => m.UpdateLastBackupGroupActivityDate("1234", lastActivityDate));

    // moqAcronisService.Setup(m => m.GetActivitiesFromDate(groupName, Convert.ToDateTime("2016-08-18T13:18:40.000Z"))).Returns(activitiesResponse);


    ActivityHarvester activityHarvester = new ActivityHarvester();

    activityHarvester.PartitionId = PartitionId;
    activityHarvester.DataProvider = moqDataProvider.Object;
    activityHarvester.LogAdapter = moqLogAdapter.Object;
    activityHarvester.AcronisSvcManager = moqAcronisServiceManager.Object;
    activityHarvester.DataProviderFactory = moqDataProviderFactory.Object;
    activityHarvester.AcronisService = moqAcronisService.Object;
    activityHarvester.AssetDataProvider = moqAssetDataProvider.Object;
    activityHarvester.BackupGroupDataProvider = moqBackupGroupDataProvider.Object;
    activityHarvester.AcronisActivityDataProvider = moqAcronisActivityDataProvider.Object;


    activityHarvester.process();//*process method calls above save method method* 
    moqFactory.VerifyAll();
}
crony
  • 491
  • 5
  • 14
  • 25
  • It is not clear (at least to me) what are you trying to test. So few hints. Use some [Test Naming Convention](http://stackoverflow.com/questions/155436/unit-test-naming-best-practices). Use [Arrange-Act-Assert](http://c2.com/cgi/wiki?ArrangeActAssert) pattern for arranging and formatting code in UnitTest methods. For the Error have a look e.g. [here](http://stackoverflow.com/questions/11989717/all-invocation-on-the-mock-must-have-a-corresponding-setup). – Daniel Dušek Aug 23 '16 at 05:48

1 Answers1

1

From your example, your setup for IAcronisService.GetActivitiesFromDate shows that it is expecting lastActivityDate of 2016-08-14T20:47:05 based on the code but the error shows that you used a different date 5/24/2016 8:33:34 PM than expected. As the moq behavior is Strict, this

Causes the mock to always throw an exception for invocations that don't have a corresponding setup.

You can make the setup a little more flexible by using It.IsAny<DateTime>()

moqAcronisService
    .Setup(m => m.GetActivitiesFromDate(groupName, It.IsAny<DateTime>()))
    .Returns(activitiesResponse);

or changing the behavior in your moq factory to use Default or Loose MockBehavior.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • Thank you. That works. I have been gettin same errors and I have applied the same strategy. Thank you – crony Aug 23 '16 at 15:06
  • Ok cool. glad to help. If this resolves your issue don't forget to mark it as answered. – Nkosi Aug 23 '16 at 15:07
  • So for the same test method, I have covered If condition. But I need to cover the else condition as well and I know what to do. rather than sending the null, just need to pass some value. then its go to the else condition. For that I need to write the same test method with adding one line/assigning value. My question was, is there any way that we just pass the value from outside rather writing the same test methods for one line? – crony Aug 23 '16 at 15:25
  • create a setup method in you test that holds the common code. then in your targeted test methods you call the common setup and you do the specific setups you need for that test to avoid the repeated code. – Nkosi Aug 23 '16 at 15:28
  • if possible could you please provide some ref/link that i can look at? I have no idea how to do that? – crony Aug 23 '16 at 15:30
  • FYI- I was talking about first if-else statement from above save method. Please give me some idea. Thank you – crony Aug 23 '16 at 15:31