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();
}
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.
Related
I've managed to create a payment using the C# .NET SDK, however it keeps showing up as 'unapplied' when I check in QBO.
I am providing the Invoice ID and tried to follow their developer API documentation but I been at this so long now that maybe I am missing something?
The following code creates the payment but doesn't 'receive' the payment towards the invoice, is there something I missed or need to do in order for the two to be linked together?
Payment payment = new Payment
{
ProcessPayment = false,
CustomerRef = new ReferenceType { name = customer.DisplayName, Value = customer.Id },
CurrencyRef = new ReferenceType { type = "Currency", Value = "CAD" },
TotalAmt = amount,
TotalAmtSpecified = true
};
if (method == PaymentTypes.Cash)
{
var paymentType = paymentMethods.FirstOrDefault(o => o.Id == "1");
if (paymentType != null)
{
payment.PaymentMethodRef = new ReferenceType()
{name = paymentType.Name, Value = paymentType.Id};
}
}
if (method == PaymentTypes.DebitCard)
{
var paymentType = paymentMethods.FirstOrDefault(o => o.Id == "9");
if (paymentType != null)
{
payment.PaymentMethodRef = new ReferenceType()
{ name = paymentType.Name, Value = paymentType.Id };
}
}
if (method == PaymentTypes.CreditCard)
{
var paymentType = paymentMethods.FirstOrDefault(o => o.Id == "8");
if (paymentType != null)
{
payment.PaymentMethodRef = new ReferenceType()
{ name = paymentType.Name, Value = paymentType.Id };
}
}
List<LinkedTxn> linkedTxns = new List<LinkedTxn>
{
new LinkedTxn()
{
TxnId = invoice.Id,
TxnType = TxnTypeEnum.Invoice.ToString()
},
};
foreach (Line line in invoice.Line)
{
//line.Amount = amount;
//line.AmountSpecified = true;
line.Received = amount;
line.ReceivedSpecified = true;
line.DetailType = LineDetailTypeEnum.PaymentLineDetail;
line.DetailTypeSpecified = true;
line.LinkedTxn = linkedTxns.ToArray();
}
payment.DepositToAccountRef = new ReferenceType() { Value = "5" };
payment.Line = invoice.Line;
payment.PaymentRefNum = reference;
DataService dataService = new DataService(serviceContext);
dataService.Add<Payment>(payment);
This is not an answer. However there's too much to add to the comments. I'm hoping this will be a helpful starting point (if not I'll remove it later).
Firstly I'd suggest refactoring your code and parameterise your variables. Doing so you should be able to preform repeatable testing in isolation.
When you preform the dataService.Add<Payment>(payment), store the response object as it may offer clues on how the request was processed. Alternatively if this is suppressing error messages, you might want to try an use Postman to send HTTP requests. This may help determine what's parameters are missing/ incorrect.
Avoid creating objects that are partially assigned it makes it a lot easier to read 7 work out which properties need to be assigned.
Also if you have a look at Full update a payment section on https://developer.intuit.com/app/developer/qbo/docs/api/accounting/all-entities/payment
the json payload has an additional Line with the property TxnType set to CreditMemo. I would assume you'll need to add something like ReceivePayment or CreditCardPayment?
To refactor your code consider:
// TODO - Set variables for testing purposes.
// This can be added as params to a method.
decimal amount = 100;
string reference = "";
string invoiceId = ""; // invoice.Id
string customerDisplayName = ""; //customer.DisplayName
string customerId = ""; //customer.Id
string paymentName = "Cash"; // paymentType.Name
string paymentId = "1"; // paymentType.Id
List<Line> lines = new List<Line>(); // invoice.Line
if(lines.Count() == 0)
{
// TODO: You might want to check there are lines?
throw new ArgumentException("No invoice.");
}
Line[] invoiceLines = lines.Select(m => new Line()
{
AnyIntuitObject = m.AnyIntuitObject,
Amount = m.Amount,
AmountSpecified = m.AmountSpecified,
CustomField = m.CustomField,
Id = m.Id,
LineNum = m.LineNum,
Description = m.Description,
DetailType = LineDetailTypeEnum.PaymentLineDetail, //m.DetailType,
DetailTypeSpecified = true, //m.DetailTypeSpecified,
LinkedTxn = new List<LinkedTxn>
{
new LinkedTxn()
{
TxnId = invoiceId,
TxnType = TxnTypeEnum.Invoice.ToString() // TODO: Should this be ReceivePayment?
},
}.ToArray(), //m.LinkedTxn,
LineEx = m.LineEx,
Received = amount, //m.Received,
ReceivedSpecified = true // m.ReceivedSpecified
}).ToArray();
Payment payment = new Payment
{
ProcessPayment = false,
CustomerRef = new ReferenceType { name = customerDisplayName, Value = customerId },
CurrencyRef = new ReferenceType { type = "Currency", Value = "CAD" },
TotalAmt = amount,
TotalAmtSpecified = true,
DepositToAccountRef = new ReferenceType() { Value = "5" },
Line = invoiceLines, // Variable is for debugging purposes - it should be inline or call a method.
PaymentRefNum = reference,
PaymentMethodRef = new ReferenceType()
{
name = paymentName,
Value = paymentId,
}
};
DataService dataService = new DataService(serviceContext);
Payment results = dataService.Add<Payment>(payment);
var json = JsonConvert.SerializeObject(results);
Console.Write(json); // TODO - Use break point/ or write response somewhere for clues.
I need to refactor the below code so that the deleted_at logic will be outside of the foreach (var app in data) loop. I tried to create the list guids and then add guids to it but its not working because model.resources is inside the loop and it is still deleting all the apps.
I need deleted_at logic outside because I'm trying to delete all apps which are in the database but are not in new data that I'm receiving from API.
If you have a better approach on my code I would love to see that, Thank you.
public async Task GetBuilds()
{
var data = new List<GetBuildTempClass>();
var guids = new List<GetBuildTempClass>();
using (var scope = _scopeFactory.CreateScope())
{
var _DBcontext = scope.ServiceProvider.GetRequiredService<PCFStatusContexts>();
foreach (var app in data)
{
var request = new HttpRequestMessage(HttpMethod.Get,
"apps/" + app.AppGuid + "/builds?per_page=200&order_by=updated_at");
var response = await _client_SB.SendAsync(request);
var json = await response.Content.ReadAsStringAsync();
BuildsClass.BuildsRootObject model =
JsonConvert.DeserializeObject<BuildsClass.BuildsRootObject>(json);
foreach (var item in model.resources)
{
var x = _DBcontext.Builds.FirstOrDefault(o =>
o.Guid == Guid.Parse(item.guid));
if (x == null)
{
_DBcontext.Builds.Add(new Builds
{
Guid = Guid.Parse(item.guid),
State = item.state,
CreatedAt = item.created_at,
UpdatedAt = item.updated_at,
Error = item.error,
CreatedByGuid = Guid.Parse(item.created_by.guid),
CreatedByName = item.created_by.name,
CreatedByEmail = item.created_by.email,
AppGuid = app.AppGuid,
AppName = app.AppName,
Foundation = 2,
Timestamp = DateTime.Now
});
}
else if (x.UpdatedAt != item.updated_at)
{
x.State = item.state;
x.UpdatedAt = item.updated_at;
x.Timestamp = DateTime.Now;
}
var sqlresult = new GetBuildTempClass
{
AppGuid = Guid.Parse(item.guid)
};
guids.Add(sqlresult);
}
//var guids = model.resources.Select(r => Guid.Parse(r.guid));
var builds = _DBcontext.Builds.Where(o =>
guids.Contains(o.Guid) == false &&
o.Foundation == 2 && o.DeletedAt == null);
foreach (var build_item in builds)
{
build_item.DeletedAt = DateTime.Now;
}
}
await _DBcontext.SaveChangesAsync();
}
}
I got it working I added var guids = new List < Guid > (); list to store data,
added guids.Add(Guid.Parse(item.guid)); to populate the list and finally wrote var builds = _DBcontext.Builds.Where(o = >guids.Contains(o.Guid) == false && o.Foundation == 2 && o.DeletedAt == null); outside the loop.
If anyone has a better suggestion please add a new answer.
public async Task GetBuilds() {
var data = new List < GetBuildTempClass > ();
var guids = new List < Guid > ();
using(var scope = _scopeFactory.CreateScope()) {
var _DBcontext = scope.ServiceProvider.GetRequiredService < PCFStatusContexts > ();
foreach(var app in data) {
var request = new HttpRequestMessage(HttpMethod.Get, "apps/" + app.AppGuid + "/builds?per_page=200&order_by=updated_at");
var response = await _client_SB.SendAsync(request);
var json = await response.Content.ReadAsStringAsync();
BuildsClass.BuildsRootObject model = JsonConvert.DeserializeObject < BuildsClass.BuildsRootObject > (json);
foreach(var item in model.resources) {
var x = _DBcontext.Builds.FirstOrDefault(o = >o.Guid == Guid.Parse(item.guid));
if (x == null) {
_DBcontext.Builds.Add(new Builds {
Guid = Guid.Parse(item.guid),
State = item.state,
CreatedAt = item.created_at,
UpdatedAt = item.updated_at,
Error = item.error,
CreatedByGuid = Guid.Parse(item.created_by.guid),
CreatedByName = item.created_by.name,
CreatedByEmail = item.created_by.email,
AppGuid = app.AppGuid,
AppName = app.AppName,
Foundation = 2,
Timestamp = DateTime.Now
});
}
else if (x.UpdatedAt != item.updated_at) {
x.State = item.state;
x.UpdatedAt = item.updated_at;
x.Timestamp = DateTime.Now;
}
guids.Add(Guid.Parse(item.guid));
}
}
var builds = _DBcontext.Builds.Where(o = >guids.Contains(o.Guid) == false && o.Foundation == 2 && o.DeletedAt == null);
foreach(var build_item in builds) {
build_item.DeletedAt = DateTime.Now;
}
await _DBcontext.SaveChangesAsync();
}
}
I have an Asp.Net MVC 5 using Entity Framework 6. I am using Unity.MVC5 Version 1.2.3.0
The issue I am having is that I would get the following error on certain scenarios when saving to the database
Additional information: The operation failed: The relationship could
not be changed because one or more of the foreign-key properties is
non-nullable. When a change is made to a relationship, the related
foreign-key property is set to a null value. If the foreign-key does
not support null values, a new relationship must be defined, the
foreign-key property must be assigned another non-null value, or the
unrelated object must be deleted.
After troubleshooting the issue I believe it has to do with how I have Unity.MVC5 configured. Here is my Unity.Config.cs
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterTypes(AllClasses.FromLoadedAssemblies(), WithMappings.FromMatchingInterface, WithName.Default);
container.RegisterType<IUnitOfWork, UnitOfWork>(new InjectionConstructor(new MasterContext()));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
So my controller would have something like this
private IService _Service;
MyController(IService service)
{
_Service = service;
}
However it looks like the data is not refreshing, Although when I use a SQL Profiler , it shows as it is making a call but the data is not refreshed as I do a breakpoint it still has old data. If I do away with the Unity.MVC injecting the classes, then the data gets refreshed and savechanges works fine.
I am overwriting the EF Context SaveChanges , here is the code
public override int SaveChanges()
{
var autoDetectChanges = Configuration.AutoDetectChangesEnabled;
try
{
Configuration.AutoDetectChangesEnabled = false;
ChangeTracker.DetectChanges();
var errors = GetValidationErrors().ToList();
if (errors.Any())
{
throw new DbEntityValidationException("Validation errors found during save.", errors);
}
//For modified column
var changedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Modified)
.Select(t => new
{
Original = t.OriginalValues.PropertyNames.ToDictionary(pn => pn, pn => t.OriginalValues[pn]),
Current = t.CurrentValues.PropertyNames.ToDictionary(pn => pn, pn => t.CurrentValues[pn]),
objectContext = ((IObjectContextAdapter)this).ObjectContext,
ent = t,
});
foreach (var item in changedInfo)
{
if (GetTableInformation.GetTableName(item.objectContext, item.ent) != "HistoryLogs")
{
var result = GetDifference.GetChangedValues(item.Original, item.Current, item.objectContext, item.ent);
HistoryLog history = new HistoryLog();
history.Description = result[0];
history.TableFields = result[1];
history.UserId = userId;
history.TableAction = "Modified";
history.PrimaryKeyValue = Convert.ToInt32(result[2]);
history.TableName = result[3];
if (history.TableName == "MainRates")
{
MainRate rate = MainRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
history.InstitutionId = rate.InstitutionId;
}
else if (history.TableName == "ProgramRates")
{
ProgramRate rate = ProgramRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
history.InstitutionId = rate.InstitutionId;
}
else
{
int institutiondId;
if (int.TryParse(result[4], out institutiondId))
{
history.InstitutionId = institutiondId;
}
else
{
history.InstitutionId = null;
}
}
//InstitutionName and OPEID are being updated by trigger(executer after each insert operations)
//Check if there is any modified column or not
if (!string.IsNullOrEmpty(history.TableFields))
HistoryLogs.Add(history);
}
}
//For Deleted columns
var deletedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Deleted)
.Select(t => new
{
Original = t.OriginalValues.PropertyNames.ToDictionary(pn => pn, pn => t.OriginalValues[pn]),
objectContext = ((IObjectContextAdapter)this).ObjectContext,
ent = t,
});
foreach (var item in deletedInfo)
{
if (GetTableInformation.GetTableName(item.objectContext, item.ent) != "HistoryLogs")
{
var result = GetDifference.GetDeletedValues(item.Original, item.objectContext, item.ent);
HistoryLog history = new HistoryLog();
history.Description = result[0];
history.TableFields = result[1];
history.UserId = userId;
history.TableAction = "Deleted";
history.PrimaryKeyValue = Convert.ToInt32(result[2]);
history.TableName = result[3];
if (history.TableName == "MainRates")
{
int locationRateId = (int)item.Original["LocationRateId"];
history.InstitutionId = LocationRates.SingleOrDefault(l => l.Id == locationRateId).InstitutionId;
}
else if (history.TableName == "ProgramRates")
{
ProgramRate rate = ProgramRates.SingleOrDefault(r => r.RateId == history.PrimaryKeyValue);
history.InstitutionId = rate.InstitutionId;
}
else
{
history.InstitutionId = result[4] == null ? null : (int?)int.Parse(result[4]);
}
//InstitutionName and OPEID are being updated by trigger(executer after each insert operations)
history.InstitutionName = "";
history.OpeidNumber = "";
//Check if there is any modified column or not
if (!string.IsNullOrEmpty(history.TableFields))
HistoryLogs.Add(history);
}
}
// For data that is added
string[] applicableTables = new string[] { "EligiblePrograms", "Fees", "LocationRates", "MainRates", "ProgramRates" };
var addedInfo = ChangeTracker.Entries().Where(t => t.State == EntityState.Added)
.Select(t => new
{
Current = t.CurrentValues.PropertyNames.ToDictionary(pn => pn, pn => t.CurrentValues[pn]),
ObjectContext = ((IObjectContextAdapter)this).ObjectContext,
Entity = t,
}).ToList();
//Placing this here adds the primary keys to the new values before saving their history.
Configuration.ValidateOnSaveEnabled = false;
int rVal = base.SaveChanges();
foreach (var item in addedInfo)
{
string tableName = GetTableInformation.GetTableName(item.ObjectContext, item.Entity);
if (applicableTables.Contains(tableName))
{
var result = GetDifference.GetDeletedValues(item.Current, item.ObjectContext, item.Entity);
HistoryLog history = new HistoryLog();
history.Description = result[0];
history.TableFields = result[1];
history.UserId = userId;
history.TableAction = "Added";
history.PrimaryKeyValue = Convert.ToInt32(result[2]);
history.TableName = result[3];
if (history.TableName == "MainRates")
{
history.InstitutionId = ((MainRate)item.Entity.Entity).InstitutionId;
}
else if (history.TableName == "ProgramRates")
{
history.InstitutionId = ((ProgramRate)item.Entity.Entity).InstitutionId;
}
else
{
history.InstitutionId = result[4] == null ? null : (int?)int.Parse(result[4]);
}
history.InstitutionName = "";
history.OpeidNumber = "";
//Check if there is any modified column or not
if (!string.IsNullOrEmpty(history.TableFields))
HistoryLogs.Add(history);
}
}
rVal += base.SaveChanges();
return rVal;
}
finally
{
Configuration.AutoDetectChangesEnabled = autoDetectChanges;
}
}
Then my Service class will do something like this:
Header header = _uow.MyRepository.GetByHeaderId(model.Id, model.HeaderId);
header.WebAddresses = string.Join(",", model.WebAddresses.ToArray());
header.Date = DateTime.Parse(model.Date);
header.IsField1 = model.Field1;
header.Field2 = model.Field2;
header.Field3 = model.Field3;
_uow.SaveChanges();
I'm experimenting with Couchbase + Xamarin.Forms trying to do a simple search, showing the results in a ListView but I've stuck. :(
Someone know how to add the rows/documents of a query in a list?
public List<Visitor> SearchRecord (string word)
{
var viewByName = db.GetView ("ByName");
viewByName.SetMap((doc, emit) => {
emit (new object[] {doc["first_name"], doc["last_name"]}, doc);
}, "2");
var visitorQuery = viewByName.CreateQuery();
visitorQuery.StartKey = new List<object> {word};
// visitorQuery.EndKey = new List<object> {word, new Dictionary<string, object>()};
visitorQuery.Limit = 100;
var visitors = visitorQuery.Run();
var visitorList = new List<Visitor> ();
foreach (var visitor in visitors) {
// visitorList.Add(visitor.Document); <-- Error.
System.Console.WriteLine(visitor.Key);
}
return visitorList;
}
I get the error messages:
Error CS1501: No overload for method Add' takes2' arguments
(CS1501) (Demo_Couchbase.Droid) Error CS1502: The best overloaded
method match for
System.Collections.Generic.List<Demo_Couchbase.Visitor>.Add(Demo_Couchbase.Visitor)'
has some invalid arguments (CS1502) (RegistroAgil_Couchbase.Droid)
Error CS1503: Argument#1' cannot convert Couchbase.Lite.Document'
expression to typeDemo_Couchbase.Visitor' (CS1503)
(Demo_Couchbase.Droid)
Thank you in advance for any help you can provide.
There is problem in your mapping part. You can directly cast documents on GetView.
You can try bellow code.
public List<Visitor> SearchRecord (string word)
{
var viewByName = db.GetView<Visitor>("ByName","ByName");
var visitorQuery = viewByName.CreateQuery();
visitorQuery.StartKey = new List<object> {word};
visitorQuery.Limit = 100;
var visitors = visitorQuery.Run();
var visitorList = new List<Visitor> ();
foreach (var visitor in visitors) {
visitorList.Add(visitor.Document);
System.Console.WriteLine(visitor.Key);
}
return visitorList;
}
I don't know if this is the most elegant solution though but my code works fine now.
Visitor ToRecord(Document d) {
var props = d.Properties;
return new Visitor {
Id = props["_id"].ToString(),
FirstName = (string)props["first_name"],
LastName = (string)props["last_name"],
Occupation = (string)props["occupation"],
Company = (string)props["company"],
Email = (string)props["email"],
Phone = (string)props["phone"],
Birthday = (string)props["birthday"],
LastVisit = (string)props["last_visit"],
LocalImagePath = (string)props["local_image_path"],
Type = (string)props["type"],
CreatedAt = (string)props["created_at"],
UpdatedAt = (string)props["updated_at"],
DeletedAt = (string)props["deleted_at"]
};
}
public List<Visitor> SearchRecord (string word)
{
var viewByName = db.GetView ("ByName");
viewByName.SetMap((doc, emit) => {
if ((doc.ContainsKey("type") && doc["type"].ToString() == "visitor") && (doc.ContainsKey("deleted_at") && doc["deleted_at"] == null))
emit (new [] {doc["first_name"], doc["last_name"]}, doc);
}, "2");
var visitorQuery = viewByName.CreateQuery();
visitorQuery.StartKey = word;
visitorQuery.Limit = 50;
var rows = visitorQuery.Run();
var visitorList = new List<Visitor> ();
for (int i = 0; i < rows.Count (); i++) {
var row = rows.GetRow (i);
var name = row.Document.GetProperty ("first_name").ToString ().ToLower () + " " + row.Document.GetProperty ("last_name").ToString ().ToLower ();
if (name.Contains (word))
visitorList.Add(ToRecord(row.Document));
}
return visitorList;
}
I am trying to get test case results(passed/failed/blocked) from TestSuite under a test plan.
Using below code to do this.
public List<ScoreBoard> GetTestStatistics(string teamProject, string selectedTestPlan)
{
// 1. Connect to TFS and Get Test Managemenet Service and Get all Test Plans
string serverName = "*********";
var server = new Uri(serverName);
var tfs = TfsTeamProjectCollectionFactory
.GetTeamProjectCollection(server);
var service = tfs.GetService<ITestManagementService>();
var testProject = service.GetTeamProject(teamProject);
var plan = testProject.TestPlans.Query("SELECT * FROM TestPlan").Where(tp => tp.Name == selectedTestPlan).FirstOrDefault();
List<ScoreBoard> scoreboards = new List<ScoreBoard>();
var testSuits = new List<IStaticTestSuite>();
if (plan.RootSuite != null)
{
testSuits.AddRange(TestSuiteHelper.GetTestSuiteRecursive(plan.RootSuite));
}
TestPlan testPlan = new TestPlan() { Id = plan.Id, Name = plan.Name, TestSuites = testSuits };
for (int i = 0; i < testPlan.TestSuites.Count; i++)
{
var ts = testPlan.TestSuites[i];
var scoreboard = new ScoreBoard();
scoreboard.TeamProject = teamProject;
scoreboard.TestPlan = selectedTestPlan;
scoreboard.Id = ts.Id;
scoreboard.Title = ts.Title;
scoreboard.State = ts.State.ToString();
scoreboard.TestCaseCount = ts.TestCases.Count;
int totalTestSteps = 0;
List<string> testStepScores = new List<string>();
foreach (var tc in ts.TestCases)
{
foreach (var a in tc.TestCase.Actions)
{
totalTestSteps = totalTestSteps + 1;
}
var testResults = testProject.TestResults.ByTestId(tc.TestCase.TestSuiteEntry.Id);
foreach (var result in testResults)
{
for (int actionIndex = 0; actionIndex < tc.TestCase.Actions.Count; actionIndex++)
{
var action = tc.TestCase.Actions[actionIndex];
if (!(action is ITestStep))
{
continue;
}
var step = action as ITestStep;
var topIteration = result.Iterations.FirstOrDefault();
if (topIteration == null)
continue;
var test = topIteration.Actions[actionIndex];
testStepScores.Add(topIteration.Actions[actionIndex].Outcome.ToString());
}
}
}
scoreboard.TestStepCount = totalTestSteps;
scoreboard.TestStepPassedCount = testStepScores.Where(tsp => tsp == "Passed").ToList().Count;
scoreboard.TestStepFailedCount = testStepScores.Where(tsp => tsp == "Failed").ToList().Count;
scoreboard.TestStepOutstandingCount = testStepScores.Where(tsp => tsp == "None").ToList().Count;
scoreboards.Add(scoreboard);
}
return scoreboards;
}
I am not getting correct result for passed test/Failed/Outstanding test count.
When I debugged into this, observed some property are showing message "Function evaluation disabled because a previous function evaluation timed out. You must continue execution to reenable function evaluation."
Can I get how many test cases are passed under the test suite ?
What could be the problem here?