Unit testing if text == null - c#

I am doing some unit tests with microsoft unit testing
I have this piece of code:
public void AddComment(Case c, string text)
{
if (text == null)
{
return;
}
var comment = UnitOfWork.GetRepository<CaseComment>().Create();
comment.Case = c;
comment.Account = _userInfoProvider.UserName;
comment.DateUtc = DateTimeHelper.UtcNow();
comment.Text = text;
UnitOfWork.GetRepository<CaseComment>().Insert(comment);
}
And I have a Unit test for this piece of cdoe:
if (text == null)
{
return;
}
I the unit test like this:
[TestMethod]
public void BaseProcess_Should_AddCommentIfNull()
{
string text = null;
var result = string.IsNullOrEmpty(text);
Assert.AreEqual(text, null);
}
It shows green. But the code coverage is still yellow and not blue.
Thank you
I have it now like this:
[TestMethod]
public void BaseProcess_Should_AddCommentIfNull()
{
string comment = "Comment";
var newInstance = new Case
{
Reference = comment,
DateSubmitted = DateTime.Now,
Status = CaseStatus.Submitted,
};
string text = null;
var result = string.IsNullOrEmpty(text);
Action act = () => CorrectionRequestCaseProcess.AddComment(newInstance, comment);
Assert.AreEqual(text, null);
}
But if I do it like this:
[TestMethod]
public void BaseProcess_Should_AddCommentIfNull()
{
string comment = "";
var newInstance = new Case
{
Reference = comment,
DateSubmitted = DateTime.Now,
Status = CaseStatus.Submitted,
};
string text = null;
var result = string.IsNullOrEmpty(text);
Action act = () => CorrectionRequestCaseProcess.AddComment(newInstance, text);
Assert.AreEqual(text, null);
}
Nothing changedenter code here
And I wrote a other unit test like this:
[TestMethod]
public void BaseProcess_should_equalToNull()
{
string comment = "Comment";
var newInstance = new Case
{
Reference = comment,
DateSubmitted = DateTime.Now,
Status = CaseStatus.Submitted,
};
var newComment = new CaseComment();
newComment.Case = newInstance;
newComment.Account = _userInfoProvider.UserName;
newComment.DateUtc = DateTimeHelper.UtcNow();
newComment.Text = comment;
var comment2 = _testUnitOfWork.GetRepository<CaseComment>().Create();
_testUnitOfWork.GetRepository<CaseComment>().Insert(newComment);
}

You should add an additional test case that text variable not equal to null and verify that repository invoked. After that, the coverage of the function will be %100.

Related

unit testing with mock

I have to unit test a function (SendMessageNetSkyToAgenceGrp), and inside this function there is a service that I want to mock (EnvoyerNotificationSms.SendMessageNetSky(signalRMessage)):
Here is the code i want to test :
public void SendMessageNetSkyToAgenceGrp(
int agenceId,
string message,
string name,
bool addAgenceLibInMsg = true,
SignalRMessageThemeEnum theme = SignalRMessageThemeEnum.Information)
{
Agence agence = AgenceCoreService.GetAgenceById(agenceId);
if (agence == null || (string.IsNullOrEmpty(agence.Libelle) && addAgenceLibInMsg))
{
return;
}
string finalMessage = (message + (addAgenceLibInMsg ? agence.Libelle : ""));
string groupName = string.Empty;
if (theme == SignalRMessageThemeEnum.NotificationSms)
{
groupName = SignalRConstantes.GRP_SMSAGENCE + SignalRConstantes.SEPARATOR + agenceId;
}
else
{
groupName = (SignalRConstantes.GRP_AGENCE + SignalRConstantes.SEPARATOR + agenceId);
}
SignalRMessage signalRMessage = new SignalRMessage(name, "", finalMessage, groupName, theme);
EnvoyerNotificationSms.SendMessageNetSky(signalRMessage);
}
And here is the test code:
[Fact(DisplayName = "Vérifier l'appel à l'infra IEnvoyerNotificationSms")]
public void SendMessageNetSkyToAgenceGrp_CasNormal_ResultatOk()
{
// Arange
var envoyerNotificationSmMock = new Mock<IEnvoyerNotificationSms>();
envoyerNotificationSmMock.Setup(envoyerNotifSms => envoyerNotifSms.SendMessageNetSky(It.IsAny<SignalRMessage>())).Verifiable();
var SignalRCoreService = LocalIocManager.Resolve<ISignalRCoreService>();
// Act
LocalIocManager.IocContainer.UseInstance(envoyerNotificationSmMock.Object, IfAlreadyRegistered.Replace);
SignalRCoreService.SendMessageNetSkyToAgenceGrp(56, "testMessage", "name", true, SignalRMessageThemeEnum.NotificationSms);
// Assert
envoyerNotificationSmMock.Verify(envoyerNotifSms => envoyerNotifSms.SendMessageNetSky(It.IsAny<SignalRMessage>()), Times.Once());
}
But when I execute the test I get an error telling me that the service I want to mock is null (EnvoyerNotificationSms.SendMessageNetSky(signalRMessage);)
The error is : 'Object reference not set to an instance of an object.' in the line EnvoyerNotificationSms.SendMessageNetSky(signalRMessage);
How can I solve this issue?
After checking the problem was the order of these lines :
var SignalRCoreService = LocalIocManager.Resolve<ISignalRCoreService>();
// Act
LocalIocManager.IocContainer.UseInstance(envoyerNotificationSmMock.Object, IfAlreadyRegistered.Replace);
In the second line has no effect, because the service i want to mock is already created in the first line. So the solution was to change the order of the two lines.

How to inject a variable into every class or method in c#

I have the following code.
[HttpGet]
public async Task<List<TenantManagementWebApi.Entities.SiteCollection>> Get()
{
var tenant = await TenantHelper.GetActiveTenant();
var siteCollectionStore = CosmosStoreFactory.CreateForEntity<TenantManagementWebApi.Entities.SiteCollection>();
await siteCollectionStore.RemoveAsync(x => x.Title != string.Empty); // Removes all the entities that match the criteria
string domainUrl = tenant.TestSiteCollectionUrl;
string tenantName = domainUrl.Split('.')[0];
string tenantAdminUrl = tenantName + "-admin.sharepoint.com";
KeyVaultHelper keyVaultHelper = new KeyVaultHelper();
await keyVaultHelper.OnGetAsync(tenant.SecretIdentifier);
using (var context = new OfficeDevPnP.Core.AuthenticationManager().GetSharePointOnlineAuthenticatedContextTenant(tenantAdminUrl, tenant.Email, keyVaultHelper.SecretValue))
{
Tenant tenantOnline = new Tenant(context);
SPOSitePropertiesEnumerable siteProps = tenantOnline.GetSitePropertiesFromSharePoint("0", true);
context.Load(siteProps);
context.ExecuteQuery();
List<TenantManagementWebApi.Entities.SiteCollection> sites = new List<TenantManagementWebApi.Entities.SiteCollection>();
foreach (var site in siteProps)
{
if(site.Template.Contains("SITEPAGEPUBLISHING#0") || site.Template.Contains("GROUP#0"))
{
string strTemplate= default(string);
if(site.Template.Contains("SITEPAGEPUBLISHING#0"))
{
strTemplate = "CommunicationSite";
};
if (site.Template.Contains("GROUP#0"))
{
strTemplate = "Modern Team Site";
};
try
{
Guid id = Guid.NewGuid();
Entities.SiteCollection sc = new Entities.SiteCollection()
{
Id = id.ToString(),
Owner = site.Owner,
Template = strTemplate,
Title = site.Title,
Active = false,
Url = site.Url
};
var added = await siteCollectionStore.AddAsync(sc);
sites.Add(sc);
}
catch (System.Exception ex)
{
throw ex;
}
}
}
return sites;
};
}
However the following lines, I am repeating them on every method:
var tenant = await TenantHelper.GetActiveTenant();
var siteCollectionStore = CosmosStoreFactory.CreateForEntity<TenantManagementWebApi.Entities.SiteCollection>();
await siteCollectionStore.RemoveAsync(x => x.Title != string.Empty); // Removes all the entities that match the criteria
string domainUrl = tenant.TestSiteCollectionUrl;
string tenantName = domainUrl.Split('.')[0];
string tenantAdminUrl = tenantName + "-admin.sharepoint.com";
KeyVaultHelper keyVaultHelper = new KeyVaultHelper();
await keyVaultHelper.OnGetAsync(tenant.SecretIdentifier);
I will have lots of API controllers on my project
Is there an easy way (not refactor as a method), to make my code cleaner and inject the variables I need without copying and pasting every single time?

C# : set default payment method in stripe

I am new in stripe, how can we set default payment method in stripe.
And can we pass cardId/sourceId to charge customer along with customerId.
Code:-
private static async Task<string> ChargeCustomer(string customerId)
{
return await System.Threading.Tasks.Task.Run(() =>
{
var myCharge = new StripeChargeCreateOptions
{
Amount = 50,
Currency = "gbp",
Description = "Charge for property sign and postage",
CustomerId = customerId
};
var chargeService = new StripeChargeService();
var stripeCharge = chargeService.Create(myCharge);
return stripeCharge.Id;
});
}
And 1 more question, how to get charge-list, I am using below code but getting exception(conversion error):-
private IEnumerable<StripeCharge> GetChargeList()
{
var chargeService = new StripeChargeService();
return chargeService.List();
}
This is what I ended up doing. Not sure why Stripe Checkout didn't set the card for the subscription setup as the default. Anyway, this fires triggered from the payment_intent.succeeded web hook. Sure there is a better way, but...
var customerService = new CustomerService(Configs.STRIPE_SECRET_KEY);
var c = customerService.Get(pi.CustomerId);
if (!string.IsNullOrEmpty(c.InvoiceSettings.DefaultPaymentMethodId)) {
status = "already has default payment method, no action";
hsc = HttpStatusCode.OK;
return;
}
var paymentMethodService = new PaymentMethodService(Configs.STRIPE_SECRET_KEY);
var lopm = paymentMethodService.ListAutoPaging(options: new PaymentMethodListOptions {
CustomerId = pi.CustomerId,
Type = "card"
});
if (!lopm.Any()) {
status = "customer has no payment methods";
hsc = HttpStatusCode.BadRequest;
return;
}
var pm = lopm.FirstOrDefault();
customerService.Update(pi.CustomerId, options: new CustomerUpdateOptions {
InvoiceSettings = new CustomerInvoiceSettingsOptions {
DefaultPaymentMethodId = pm.Id
}
});
hsc = HttpStatusCode.OK;
return;
We can pass cardId/BankAccountId/TokenId/SourceId in SourceTokenOrExistingSourceId property of StripeChargeCreateOptions,
private static async Task<string> ChargeCustomer(string customerId, string cardId)
{
try
{
return await System.Threading.Tasks.Task.Run(() =>
{
var myCharge = new StripeChargeCreateOptions
{
Amount = 50,
Currency = "gbp",
Description = "Charge for property sign and postage",
CustomerId = customerId,
SourceTokenOrExistingSourceId = cardId
};
var chargeService = new StripeChargeService();
var stripeCharge = chargeService.Create(myCharge);
return stripeCharge.Id;
});
}
catch(Exception ex)
{
return "";
}
}
To set/change default payment method:-
public void ChangeDefaultPayment(string customerId, string sourceId)
{
var myCustomer = new StripeCustomerUpdateOptions();
myCustomer.DefaultSource = sourceId;
var customerService = new StripeCustomerService();
StripeCustomer stripeCustomer = customerService.Update(customerId, myCustomer);
}
Still looking for how to get charge-list.

Moq - Null reference exception when trying to test ActionResult

I'm trying to learn unit testing with Moq but I keep running into the same issue. I am writing unit tests for my controller ActionResults and I don't have a problem with creating an instance of my controller and testing that it works. But I have an ActionResult that gives me a null reference exception because I am missing something with setting up my test before calling the controller.
private PersonController _controller;
private Mock<ICoreRepository> _repoCore;
private Mock<IImageRepository> _repoImage;
[TestInitialize]
public void Setup()
{
_repoCore = new Mock<ICoreRepository>();
_repoImage = new Mock<IImageRepository>();
_controller = new PersonController(_repoImage.Object)
{
CrmCoreRepository = _repoCore.Object,
//ImageRepository = _repoImage.Object
};
}
[TestMethod]
public void UploadImage_NotNull_personImage_Test()
{
var controller = new PersonController(_repoImage.Object);
var model = new GlobalEntityModel
{
PersonModel= new PersonModel()
};
controller.CrmCoreRepository = _repoCore.Object;
var uploadedFile = new Mock<HttpPostedFileBase>();
uploadedFile
.Setup(f => f.ContentLength)
.Returns(10);
uploadedFile
.Setup(f => f.FileName)
.Returns("testimage.jpg");
var imageRepository = new Mock<IImageRepository>();
imageRepository.Setup(x => x.SaveImage(It.IsAny<HttpPostedFileBase>(), It.IsAny<ImagePaths>()));
var res = controller.AddOrUpdatePersonDetail(model, uploadedFile.Object);
Assert.IsNotNull(res);
}
In my test I create a new controller instance, model, a mock of httppostedfilebase and I try to setup the image repository saveImage.
[HttpPost]
public ActionResult AddOrUpdatePersonDetail(GlobalEntityModel model, HttpPostedFileBase personImage)
{
var uploadedImage = string.Empty;
var personImagePath = _imageRepository.RetrieveImageFilePath(ImagePaths.PersonImageFilePath);
if (personImage != null)
{
uploadedImage = _imageRepository.SaveImage(personImage, ImagePaths.PersonImageFilePath);
}
var personModel = model.PersonModel;
var personDto = Mapper.MapTo<PersonDto>(personModel);
//Update Person
personDto.CreatedBy = "Admin";
personDto.UpdatedBy = "Admin";
personDto.UpdatedOn = DateTime.Now;
if (uploadedImage != string.Empty)
{
personDto.PersonImageRef = uploadedImage;
if (personDto.PersonImageRef.Contains(personImagePath))
{
personDto.PersonImageRef = personDto.PersonImageRef.Replace(personImagePath, string.Empty);
}
if (personDto.PersonImageRef.Contains("~/Content"))
{
personDto.PersonImageRef = string.Empty;
}
}
if (personDto.Id == 0)
{
personDto.GlobalEntityGUID = model.GlobalEntityGUID;
personDto = CrmCoreRepository.AddPerson(personDto, null, null, null);
if (personDto != null)
{
personModel.GlobalEntityGUID = personDto.GlobalEntityGUID;
var personDetailModel = model.PersonDetailModel;
personDetailModel.PersonId = personDto.Id;
var personDetailDto = Mapper.MapTo<PersonDetailDto>(personDetailModel);
personDetailDto.CreatedBy = "Admin";
personDetailDto.UpdatedBy = "Admin";
personDetailDto = personDetailModel.Id == 0 ? CrmCoreRepository.AddPersonDetail(personDetailDto) : CrmCoreRepository.UpdatePersonDetail(personDetailDto);
}
}
else if (personDto.Id > 0)
{
personDto = CrmCoreRepository.UpdatePerson(personDto, null, null, null);
if (personDto != null)
{
personModel.GlobalEntityGUID = personDto.GlobalEntityGUID;
var personDetailModel = model.PersonDetailModel;
personDetailModel.PersonId = personDto.Id;
var personDetailDto = Mapper.MapTo<PersonDetailDto>(personDetailModel);
personDetailDto.CreatedBy = "Admin";
personDetailDto.UpdatedBy = "Admin";
personDetailDto = personDetailModel.Id == 0 ? CrmCoreRepository.AddPersonDetail(personDetailDto) : CrmCoreRepository.UpdatePersonDetail(personDetailDto);
}
}
return RedirectToRoute("EditEntity", new { controller = "GlobalEntity", action = "EditEntity", entityGuid = personModel.GlobalEntityGUID, entityType = "P" });
}
personImagePath as shown in the screenshot is null. Because I am not passing a parameter from my test I don't know how to make it contain a value. I am a bit confused with what to do in the unit test to fix this. Any help would be great.
You are using two different instances of IImageRepository. You need to make Setup calls on the same objects that were injected to object you are testing (PersonController - IImageRepository).
To fix it, change
var imageRepository = new Mock<IImageRepository>();
imageRepository.Setup(x => x.SaveImage(It.IsAny<HttpPostedFileBase>(),
It.IsAny<ImagePaths>()));
to (notice Returns)
_repoImage.Setup(x => x.SaveImage(It.IsAny<HttpPostedFileBase>(),
It.IsAny<ImagePaths>())).Returns("~/Content");

unit test for MvcHtmlString type

I have a method that returns MvcHtmlString, so in my unit test I'm trying to make sure that the right type comes back:
[TestMethod]
public void GetTeamNameByAlignmentTest()
{
var target01 = MockEventData().First().GetTeamNameByAlignment("HoMe");
Assert.IsInstanceOfType(target01, typeof(MvcHtmlString));
}
However the test fails
Assert.IsInstanceOfType failed. Expected type:<System.Web.Mvc.MvcHtmlString>. Actual type:<System.Web.Mvc.{Dynamic}.DynamicMvcHtmlString>
How do I properly test for MvcHtmlString return type?
EDIT:
The Method:
public MvcHtmlString GetTeamNameByAlignment(String alignment)
{
StringBuilder teamName = new StringBuilder();
if (Participants.First().Alignment.ToLower() == alignment.ToLower())
{
teamName.Append(Participants.First().Team.TeamName);
if (Participants.First().Winning == true)
{
teamName.Insert(0, "<b>");
teamName.Append("</b>");
}
}
if (Participants.Last().Alignment.ToLower() == alignment.ToLower())
{
teamName.Append(Participants.Last().Team.TeamName);
if (Participants.Last().Winning == true)
{
teamName.Insert(0, "<b>");
teamName.Append("</b>");
}
}
return MvcHtmlString.Create(teamName.ToString());
}
EDIT 2:
Mocked data:
private static IQueryable<Event> MockEventData()
{
Team team01 = new Team();
team01.TeamName = "HomeTeam";
Team team02 = new Team();
team02.TeamName = "AwayTeam";
EventParticipant participant01 = new EventParticipant();
participant01.Alignment = "home";
participant01.Team = team01;
participant01.Winning = false;
participant01.totalScore = 77;
EventParticipant participant02 = new EventParticipant();
participant02.Alignment = "away";
participant02.Team = team02;
participant02.Winning = true;
participant02.totalScore = 99;
Event event01 = new Event();
event01.Participants = new List<EventParticipant> {participant01, participant02};
IQueryable<Event> events = new List<Event> { event01 }.AsQueryable();
return events;
}
Looking at this source code for MvcHtmlString, DynamicMvcHtmlString looks to be a runtime-created subclass of MvcHtmlString. With that in mind, how about changing your assertion to:
Assert.IsTrue(target01 is MvcHtmlString);
?

Categories

Resources