using FakeXrmEasy;
using FakeItEasy;
using Microsoft.Xrm.Sdk;
using Xunit;
public class CaspPluginTests
{
[Fact]
public void Should_Call_CaspService_And_Set_Attribute()
{
// Arrange
var context = new XrmFakedContext();
var fakeService = A.Fake<ICaspService>();
// Fake the method return value
A.CallTo(() => fakeService.GetCaspMedicalData("123", "DLN456"))
.Returns("{\"status\":\"success\"}");
// Register your plugin and pass in the fake dependency
var pluginContext = context.GetDefaultPluginContext();
// Example: simulate a target entity
var target = new Entity("contact") { Id = Guid.NewGuid() };
target["pfx_contactid"] = "123";
target["pfx_dln"] = "DLN456";
pluginContext.InputParameters["Target"] = target;
// Inject the fake dependency using constructor injection or a service locator
var plugin = new CaspPlugin(fakeService); // You must design your plugin to accept it
// Act
context.ExecutePluginWith(plugin, pluginContext);
// Assert — e.g. verify attribute set based on the fake result
var updated = context.Data[target.LogicalName][target.Id];
Assert.True(updated.Contains("pfx_result"));
Assert.Equal("{\"status\":\"success\"}", updated["pfx_result"]);
}
}
Wednesday, May 7, 2025
Act Arrange 2
Act Arrnage
using Xunit;
using FakeItEasy;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Xrm.Sdk;
public class CaspServiceTests
{
private readonly IDataAccessEnvironmentVariables _envVarMock;
private readonly ISystemConfigurationService _configServiceMock;
private readonly ITraceLogger _loggerMock;
private readonly IHttpClientFactoryWrapper _httpFactoryMock;
private readonly CaspService _service;
public CaspServiceTests()
{
_envVarMock = A.Fake<IDataAccessEnvironmentVariables>();
_configServiceMock = A.Fake<ISystemConfigurationService>();
_loggerMock = A.Fake<ITraceLogger>();
_httpFactoryMock = A.Fake<IHttpClientFactoryWrapper>();
_service = new CaspService(
_envVarMock,
_configServiceMock,
_loggerMock,
_httpFactoryMock
);
}
private HttpClient CreateFakeHttpClient(HttpResponseMessage responseMessage)
{
var fakeHandler = A.Fake<HttpMessageHandler>();
A.CallTo(() => fakeHandler.Send(
A<HttpRequestMessage>._,
A<CancellationToken>._))
.Returns(responseMessage);
return new HttpClient(fakeHandler);
}
[Fact]
public void GetCaspMedicalData_ShouldThrow_WhenUrlIsMissing()
{
// Arrange
A.CallTo(() => _envVarMock
.GetEnvironmentVariableValueByDefinitionSchemaName(A<string>._))
.Returns(null);
// Act & Assert
Assert.Throws<InvalidPluginExecutionException>(() =>
_service.GetCaspMedicalData("123", "DLN456"));
}
[Fact]
public void GetCaspMedicalData_ShouldReturnResponse_WhenSuccessful()
{
// Arrange
var expectedJson = "{\"status\":\"success\"}";
var fakeHttpResponse = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(expectedJson, Encoding.UTF8, "application/json")
};
A.CallTo(() => _envVarMock
.GetEnvironmentVariableValueByDefinitionSchemaName(A<string>._))
.Returns(new Entity { ["value"] = "https://fake.url.com" });
A.CallTo(() => _configServiceMock.RetrievePFXSystemConfigRecord())
.Returns(new Entity("pfx_config"));
A.CallTo(() => _httpFactoryMock.CreateClient(A<Entity>._))
.Returns(CreateFakeHttpClient(fakeHttpResponse));
// Act
var result = _service.GetCaspMedicalData("123", "DLN456");
// Assert
Assert.Equal(expectedJson, result);
}
[Fact]
public void GetCaspMedicalData_ShouldThrow_WhenHttpReturnsNotFound()
{
// Arrange
var response = new HttpResponseMessage(HttpStatusCode.NotFound);
A.CallTo(() => _envVarMock
.GetEnvironmentVariableValueByDefinitionSchemaName(A<string>._))
.Returns(new Entity { ["value"] = "https://fake.url.com" });
A.CallTo(() => _configServiceMock.RetrievePFXSystemConfigRecord())
.Returns(new Entity("pfx_config"));
A.CallTo(() => _httpFactoryMock.CreateClient(A<Entity>._))
.Returns(CreateFakeHttpClient(response));
// Act & Assert
Assert.Throws<HttpRequestException>(() =>
_service.GetCaspMedicalData("123", "DLN456"));
}
[Fact]
public void GetCaspMedicalData_ShouldReturnEmpty_WhenInternalServerError()
{
// Arrange
var response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
A.CallTo(() => _envVarMock
.GetEnvironmentVariableValueByDefinitionSchemaName(A<string>._))
.Returns(new Entity { ["value"] = "https://fake.url.com" });
A.CallTo(() => _configServiceMock.RetrievePFXSystemConfigRecord())
.Returns(new Entity("pfx_config"));
A.CallTo(() => _httpFactoryMock.CreateClient(A<Entity>._))
.Returns(CreateFakeHttpClient(response));
// Act
var result = _service.GetCaspMedicalData("123", "DLN456");
// Assert
Assert.Equal(string.Empty, result);
}
[Fact]
public void GetCaspMedicalData_ShouldLogAndThrow_WhenUnhandledExceptionOccurs()
{
// Arrange
A.CallTo(() => _envVarMock
.GetEnvironmentVariableValueByDefinitionSchemaName(A<string>._))
.Returns(new Entity { ["value"] = "https://fake.url.com" });
A.CallTo(() => _configServiceMock.RetrievePFXSystemConfigRecord())
.Returns(new Entity("pfx_config"));
A.CallTo(() => _httpFactoryMock.CreateClient(A<Entity>._))
.Throws(new Exception("Unexpected failure"));
// Act & Assert
Assert.Throws<Exception>(() =>
_service.GetCaspMedicalData("123", "DLN456"));
A.CallTo(() => _loggerMock
.Error(A<string>._, A<string>._, A<Exception>._))
.MustHaveHappenedOnceExactly();
}
}
Sunday, March 23, 2025
Activity Party
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
public class RetrieveActivityParty
{
private readonly IOrganizationService _service;
public RetrieveActivityParty(IOrganizationService service)
{
_service = service;
}
public void GetActivityParties(Guid activityId)
{
QueryExpression query = new QueryExpression("activityparty")
{
ColumnSet = new ColumnSet("partyid", "participationtypemask")
};
query.Criteria.AddCondition("activityid", ConditionOperator.Equal, activityId);
EntityCollection results = _service.RetrieveMultiple(query);
foreach (Entity activityParty in results.Entities)
{
EntityReference party = activityParty.GetAttributeValue<EntityReference>("partyid");
int participationType = activityParty.GetAttributeValue<OptionSetValue>("participationtypemask")?.Value ?? 0;
Console.WriteLine($"Party ID: {party?.Id}, Type: {party?.LogicalName}, Participation Type: {participationType}");
}
}
}
Monday, March 10, 2025
Slpit-string
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main()
{
string url = "https://example.com/a-guid/b-guid/c-guid/d.anyextension";
if (TryExtractFields(url, out string fieldA, out string fieldBC))
{
Console.WriteLine($"a: {fieldA}");
Console.WriteLine($"b/c: {fieldBC}");
}
else
{
Console.WriteLine("Invalid URL format.");
}
}
static bool TryExtractFields(string url, out string fieldA, out string fieldBC)
{
fieldA = string.Empty;
fieldBC = string.Empty;
// Regex to match: https://{domain}/{guid}/{guid}/{guid}/filename.anyextension
Regex regex = new Regex(@"^https://[^/]+/([0-9a-fA-F-]{36})/([0-9a-fA-F-]{36})/([0-9a-fA-F-]{36})/[^/]+\.[a-zA-Z0-9]+$");
Match match = regex.Match(url);
if (match.Success)
{
fieldA = match.Groups[1].Value; // Extract GUID 'a'
fieldBC = $"{match.Groups[2].Value}/{match.Groups[3].Value}"; // Extract 'b/c' as "b-guid/c-guid"
return true;
}
return false;
}
}