Can you please suggest how to write unit test for web services in xamarin forms, I am getting error to on running
[TestFixture()]
public class LeadRepositoryTest
{
private Mock<ILeadWebService> mockLeadWebService { get; set; }
private Mock<ILeadDatabaseService> mockLeadDatabaseService { get; set; }
private LeadService leadRepository { get; set; }
public LeadRepositoryTest()
{
var repository = new MockRepository(MockBehavior.Default) { DefaultValue = DefaultValue.Empty };
mockLeadWebService = repository.Create<ILeadWebService>().As<ILeadWebService>();
mockLeadDatabaseService = repository.Create<ILeadDatabaseService>().As<ILeadDatabaseService>();
mockLeadWebService.Setup(x => x.GetNormalLeads(CommonMockData.GetLeadRequestParams())).Returns(Task.FromResult(OperationResult.CreateSuccessResult(new GetLeadsApiResponseDTO())));
leadRepository = new LeadService(mockLeadDatabaseService.Object, mockLeadWebService.Object, null, null);
}
[Test()]
public async void GetNormalLeads_WebServiceIsNotNull()
{
//Arrange
var parameters = new LeadRequestParams()
{
Offset = 0,
Limit = 20,
PageName = "Today",
};
//Act
var operationResult = await leadRepository.GetNormalLeads(parameters);
//Assert
Assert.IsNotNull(operationResult?.Data);
}
},
I think what you really need is:
var mockLeadRepository = new Mock<ILeadService>();
mockLeadRepository.Setup(x => x.GetNormalLeads(It.IsAny<Object>())).Returns(Task.FromResult(OperationResult.CreateSuccessResult(new GetLeadsApiResponseDTO())));
leadRepository = mockLeadRepository.Object;
Related
I've read Microsoft documentation on Unit Testing
Unit testing: https://learn.microsoft.com/en-us/azure/azure-functions/durable/durable-functions-unit-testing
So for example, based on the MS documentation, if this is my orchestrator:
[FunctionName("SagaToTestOrchestrator")]
public static async Task<ShippingPrice> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context)
{
var input = context.GetInput<SagaContext>();
RetryOptions _retryOptions = RetryConfiguration.GetActivityRetryOptions();
// activity to get proper orchestrator for continent for shipping partner
var supplierOrchestratorToRun = await context.CallActivityWithRetryAsync<string>("GetSupplierOrchestratorForContinent", _retryOptions, input.Continent);
// orchestrator to get the price for the shipping address
var priceForShipment =
await context.CallSubOrchestratorAsync<decimal>($"{supplierOrchestratorToRun}Orchestrator", input);
// activity to publish event for Sales / marketing
await context.CallActivityWithRetryAsync("PublishCalculatedPriceActivity", _retryOptions,(input, priceForShipment));
return new ShippingPrice()
{
Shippable = true,
Price = priceForShipment
};
}
[FunctionName("CourierAOrchestrator")]
public static async Task<decimal> CourierAOrchestrator([OrchestrationTrigger] IDurableOrchestrationContext context)
{
return 100;
}
[FunctionName("CourierBOrchestrator")]
public static async Task<decimal> CourierBOrchestrator([OrchestrationTrigger] IDurableOrchestrationContext context)
{
return 120;
}
[FunctionName("IsContinentSupported")]
public static async Task<bool> IsContinentSupported([ActivityTrigger] string continent, ILogger log)
{
var supportedContinents = new List<string>
{
"North America", "South America", "Europe",
};
return supportedContinents.Contains(continent);
}
[FunctionName("GetSupplierOrchestratorForContinent")]
public static async Task<string> GetSupplierOrchestratorForContinent([ActivityTrigger] string continent, ILogger log)
{
var courier = "";
switch (continent)
{
case "South America":
case "North America":
courier = "CourierA";
break;
case "Europe":
courier = "CourierB";
break;
}
return courier;
}
[FunctionName("PublishCalculatedPriceActivity")]
public static async Task PublishCalculatedPriceActivity([ActivityTrigger] (SagaContext context, decimal price) input, ILogger log)
{
log.LogInformation($"{input.context.Continent}: {input.price}");
}
public class ShippingPrice
{
public bool Shippable { get; set; }
public decimal Price { get; set; }
public string Message { get; set; }
}
public class SagaContext
{
public string Street { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string Continent { get; set; }
}
And my test would be something like this:
public async Task CalculatePriceForAmerica()
{
// Arrange / Given
var orchContext = new SagaContext
{
Continent = "North America"
};
var context = new Mock<IDurableOrchestrationContext>();
// mock the get input
context.Setup(m =>
m.GetInput<SagaContext>()).Returns(orchContext);
// set-up mocks for activity
context.Setup(m
=> m.CallActivityWithRetryAsync<string>("GetSupplierOrchestratorForContinent", _retryOptions, It.IsAny<object>()))
.ReturnsAsync("CourierA");
// set-up mocks for suborchstrators
context.Setup(m =>
m.CallSubOrchestratorAsync<decimal>("CourierAOrchestrator", It.IsAny<string>(), It.IsAny<object>()))
.ReturnsAsync(100);
// ACT / When
var price = await SagaToTestOrchestrator.RunOrchestrator(context.Object);
// Assert / Then
Assert.True(price.Shippable);
Assert.Equal(100, price.Price);
}
Here the issue I am facing is
setup mock data for the GetSupplierOrchestratorForContinent Activity , so ideally it should return "CourierA" as output when the actual Orchestrator method is called but it is returning null.
I am writing test for Web API application written in .NET CORE 3.1. I am using xUnit, AutoFixture & Moq for testing. I have a class that creates a new school instance in the database using Entity Framework/ DbContext. My question is how to mock dbContext & save changes, further my School DataModel has one: many relationships with SchoolBranch DataModel. I have followed this tutorial https://learn.microsoft.com/en-us/ef/ef6/fundamentals/testing/mocking
Error
Message:
Moq.MockException :
Expected invocation on the mock once, but was 0 times: m => m.Add<School>(It.IsAny<School>())
Performed invocations:
Mock<SchoolDbContext:1> (m):
No invocations performed.
Stack Trace:
Mock.Verify(Mock mock, LambdaExpression expression, Times times, String failMessage)
Mock`1.Verify[TResult](Expression`1 expression, Times times)
CreateSchoolCommandTest.ExecuteMethod_ShouldReturnNewGuidId_IfSuccess() line 50
School
public class School
{
public School()
{
this.SchoolBranches = new HashSet<SchoolBranch>();
}
public Guid SchoolID { get; set; }
public string Name { get; set; }
public ICollection<SchoolBranch> SchoolBranches { get; set; }
}
SchoolBranch
public class SchoolBranch
{
public SchoolBranch()
{
}
public Guid SchoolBranchID { get; set; }
public Guid SchoolID { get; set; }
public string Address { get; set; }
public int PhoneNumber { get; set; }
public School School { get; set; }
}
CreateSchool Class
public class CreateSchool : BaseCommand<Guid>, ICreateSchool
{
public SchoolDto SchoolDtos { get; set; }
public CreateSchool(IAppAmbientState appAmbient) : base(appAmbient) { }
public override Guid Execute()
{
try
{
var schoolId = Guid.NewGuid();
List<SchoolBranch> schoolBranches = new List<SchoolBranch>();
foreach(var item in SchoolDtos.SchoolBranchDtos)
{
schoolBranches.Add(new SchoolBranch()
{
SchoolBranchID = Guid.NewGuid(),
SchoolID = schoolId,
Address = item.Address,
PhoneNumber = item.PhoneNumber
});
}
var school = new School()
{
SchoolID = schoolId,
Name = SchoolDtos.Name,
SchoolBranches = schoolBranches
};
schoolDbContext.Schools.Add(school);
schoolDbContext.SaveChanges();
return school.SchoolID;
}
catch(Exception exp)
{
appAmbientState.Logger.LogError(exp);
throw;
}
}
}
Test Class
public class CreateSchoolCommandTest
{
private readonly ICreateSchool sut;
private readonly Mock<IAppAmbientState> appAmbientState = new Mock<IAppAmbientState>();
[Fact]
public void ExecuteMethod_ShouldReturnNewGuidId_IfSuccess()
{
//Arrange
var fixture = new Fixture();
var schoolDtoMock = fixture.Create<SchoolDto>();
var schoolDbSetMock = new Mock<DbSet<School>>();
var schoolBranchDbSetMock = new Mock<DbSet<SchoolBranch>>();
var schoolDbContextMock = new Mock<SchoolDbContext>();
//schoolDbSetMock.Setup(x => x.Add(It.IsAny<School>())).Returns((School s) => s); // this also did not work
schoolDbContextMock.Setup(m => m.Schools).Returns(schoolDbSetMock.Object);
//Act
sut.SchoolDtos = schoolDtoMock;
var actualDataResult = sut.Execute();
// Assert
Assert.IsType<Guid>(actualDataResult);
schoolDbContextMock.Verify(m => m.Add(It.IsAny<School>()), Times.Once());
schoolDbContextMock.Verify(m => m.SaveChanges(), Times.Once());
}
BaseCommand (DbContext is created here)
public abstract class BaseCommand<T>
{
protected SchoolDbContext schoolDbContext;
protected IAppAmbientState appAmbientState { get; }
public BaseCommand(IAppAmbientState ambientState)
{
this.schoolDbContext = new SchoolDbContext();
this.appAmbientState = ambientState;
}
public abstract T Execute();
}
For fix Error
You made just a little mistake. Insted of
schoolDbContextMock.Verify(m => m.Add(It.IsAny<School>()), Times.Once());
schoolDbContextMock.Verify(m => m.SaveChanges(), Times.Once());
You should have
schoolDbSetMock.Verify(m => m.Add(It.IsAny<School>()), Times.Once());
schoolDbContextMock.Verify(m => m.SaveChanges(), Times.Once());
Because you use method Add() on schoolDbContext.Schools not on schoolDbContext
For injecting dbContext
Your BaseCoommand class constructor should look like this:
public BaseCommand(IAppAmbientState ambientState, SchoolDbContext schoolDbContext)
{
this.schoolDbContext = schoolDbContext;
this.appAmbientState = ambientState;
}
Your CreateSchool class constructor:
public CreateSchool(IAppAmbientState appAmbient, SchoolDbContext schoolDbContext) : base(appAmbient, schoolDbContext) { }
And next in test you should initialize CreateSchool in test like this:
var sut = new CreateSchool(ambientState, schoolDbContextMock.Object);
And it will work
I think this is because my json gives me an array, but I don't know how it solved, this is what I did. (I'm new at this)
running in Visual Studio 2019 (xamarin.form) with web services but the url is hidden for security, so don't pay attention in that.
---my-json---
{
"cuentas":[
{
"cuenta":"0500",
"usuario":41
},
{
"cuenta":"0508",
"usuario":6
},
{
"cuenta":"0522",
"usuario":41
},
{
"cuenta":"0532",
"usuario":41
},
null
]
}
---WSClient.cs---
class WSClient
{
public async Task<T> Post<T>(string url, StringContent c)
{
var client = new HttpClient();
var response = await client.PostAsync(url, c);
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<T>(json);
}
}
----Cuenta.cs---
public class Cuenta
{
public string cuenta { get; set; }
public int usuario { get; set; }
}
------MainPage.xaml.cs-----
private async void BtnCall_Clicked(object sender, EventArgs e)
{
WSClient client = new WSClient();
string dato = "";
StringContent content = new StringContent(dato, Encoding.UTF8, "application/json");
var result = await client.Post<Cuenta>("http://www.***", content);
if (result != null) {
lblCuenta.Text = result.cuenta;
lblUsuario.Text = result.cuenta;
}
}
It doesn't show me anything and it doesn't give me any mistakes... any advice?
( I can see the json in the console if I use WriteLine in "WSClient" )
your class should look like this (using json2csharp.com)
public class Cuenta
{
public string cuenta { get; set; }
public int usuario { get; set; }
}
public class RootObject
{
public List<Cuenta> cuentas { get; set; }
}
var result = await client.Post<RootObject>("http://www.***", content);
I am writing unit test cases and I am successful in writing unit test case for Query. But I am failing to write unit test case for QueryMultiple.
For Query I am writing like this:
IEnumerable<ClientTestPurpose> fakeTestPurposes = new
List<ClientTestPurpose>()
{
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name1"},
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name2"},
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name3"}
};
_mock.SetupDapper(x => x.Query<ClientTestPurpose>(It.IsAny<string>(), null, null, true, null, null)).Returns(fakeTestPurposes);
var result = _libraryRepository.TestPurposes(clientModal.Id);
Assert.IsNotNull(result);
Assert.AreEqual(result.Count(), fakeTestPurposes.Count());
How to write for QueryMultiple:
using (var multi = _db.QueryMultiple(spName, spParams, commandType: CommandType.StoredProcedure))
{
var totals = multi.Read<dynamic>().FirstOrDefault();
var aggregates = multi.Read<StatusModel>();
var scripts = multi.Read<LibraryItemModel>();
var runs = multi.Read<RunSummaryModel>();
var filteredTotals = multi.Read<dynamic>().FirstOrDefault();
}
Apparently you use Moq.Dapper extenstions. Here is the code of SetupDapper and SetupDapperAsync method:
public static ISetup<IDbConnection, TResult> SetupDapper<TResult>(this Mock<IDbConnection> mock, Expression<Func<IDbConnection, TResult>> expression)
{
MethodCallExpression body = expression.Body as MethodCallExpression;
if ((body != null ? body.Method.DeclaringType : (Type) null) != typeof (SqlMapper))
throw new ArgumentException("Not a Dapper method.");
string name = body.Method.Name;
if (name == "Execute")
return (ISetup<IDbConnection, TResult>) DbConnectionInterfaceMockExtensions.SetupExecute(mock);
if (name == "ExecuteScalar")
return DbConnectionInterfaceMockExtensions.SetupExecuteScalar<TResult>(mock);
if (name == "Query" || name == "QueryFirstOrDefault")
return DbConnectionInterfaceMockExtensions.SetupQuery<TResult>(mock);
throw new NotSupportedException();
}
public static ISetup<IDbConnection, Task<TResult>> SetupDapperAsync<TResult>(this Mock<IDbConnection> mock, Expression<Func<IDbConnection, Task<TResult>>> expression)
{
MethodCallExpression body = expression.Body as MethodCallExpression;
if ((body != null ? body.Method.DeclaringType : (Type) null) != typeof (SqlMapper))
throw new ArgumentException("Not a Dapper method.");
if (body.Method.Name == "QueryAsync")
return DbConnectionInterfaceMockExtensions.SetupQueryAsync<TResult>(mock);
throw new NotSupportedException();
}
As you can see Moq.Dapper supports mocking only for Execute, ExecuteScalar, Query and QueryAsync methods. Therefore you probably get NotSupportedException on trying to mock QueryMultiple. To mock DB behavior you probably need introduce another level of abstraction first, as #TrueWill said in a comments. Here is just an example of idea how it can be in your case:
[Test]
public void DoSomethingWithQueryTest()
{
// Arrange
IEnumerable<ClientTestPurpose> fakeTestPurposes = new
List<ClientTestPurpose>
{
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name1" },
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name2" },
new ClientTestPurpose { PurposeID = 1, PurposeName = "Test Purpose name3" }
};
var mock = new Mock<ILibraryRepository>();
mock.Setup(x => x.TestPurposes(It.IsAny<int>())).Returns(fakeTestPurposes);
var logicService = new SomeLogicService(mock.Object);
// Act
var result = logicService.DoSomethingWithQuery(1);
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(result.Count(), fakeTestPurposes.Count());
}
[Test]
public void DoSomethingWithQueryMultipleTest()
{
// Arrange
SomeAggregate fakeTestPurposes = new SomeAggregate();
var mock = new Mock<ILibraryRepository>();
mock.Setup(x => x.TestQueryMultiple()).Returns(fakeTestPurposes);
var logicService = new SomeLogicService(mock.Object);
// Act
var result = logicService.DoSomethingWithQueryMultiple();
// Assert
Assert.IsNotNull(result);
}
public interface ILibraryRepository
{
IEnumerable<ClientTestPurpose> TestPurposes(int id);
SomeAggregate TestQueryMultiple();
}
public class LibraryRepository : ILibraryRepository
{
private readonly IDbConnection _db;
public LibraryRepository(IDbConnection db)
{
_db = db ?? throw new ArgumentNullException(nameof(db));
}
public IEnumerable<ClientTestPurpose> TestPurposes(int id)
{
return _db.Query<ClientTestPurpose>("SQL here", new { id }, null, true, null, null);
}
public SomeAggregate TestQueryMultiple()
{
string spName = "SQL here";
var spParams = new { Id = 1 };
using (var multi = _db.QueryMultiple(spName, spParams, commandType: CommandType.StoredProcedure))
{
return new SomeAggregate
{
totals = multi.Read<dynamic>().FirstOrDefault(),
aggregates = multi.Read<StatusModel>(),
scripts = multi.Read<LibraryItemModel>(),
runs = multi.Read<RunSummaryModel>(),
filteredTotals = multi.Read<dynamic>().FirstOrDefault()
};
}
}
}
public class SomeAggregate
{
public IEnumerable<dynamic> totals { get; set; }
public IEnumerable<StatusModel> aggregates { get; set; }
public IEnumerable<LibraryItemModel> scripts { get; set; }
public IEnumerable<RunSummaryModel> runs { get; set; }
public IEnumerable<dynamic> filteredTotals { get; set; }
}
/// <summary>
/// Example logic server, that just returns results from repository
/// </summary>
public class SomeLogicService
{
private readonly ILibraryRepository _repo;
public SomeLogicService(ILibraryRepository repo)
{
_repo = repo;
}
public IEnumerable<ClientTestPurpose> DoSomethingWithQuery(int id)
{
return _repo.TestPurposes(id);
}
public SomeAggregate DoSomethingWithQueryMultiple()
{
return _repo.TestQueryMultiple();
}
}
The main idea is to hide all DB specific thing behind the ILibraryRepository and move all logic that you need to test to some logic server, that will receive repository as dependency. In order code in repository should be simple, obvious, contains all DB specific logic: connection, transaction, command, object-relation mapping, etc. And you don't need to cover this code with unt tests. However you do cover code of SomeLogicService with unit tests, because this is what you really need to test. You see Dapper extension method are rather low-level abstraction, that doesn't hide details of working with DB, they are just helpers. Hope it helps.
¿How to read meta tags in SharePoint 2013 in every page with friendly url?
Thanks in advance.
Ok,
I found the answer debuggin, this work for me.
public class SEOProperties {
public string PropBrowserTitle { get; set; }
public string PropBrowserDescription { get; set; }
public string PropBrowserKeyWords { get; set; }
public string PropBrowserSiteNoIndex { get; set; }
}
private SEOProperties GetSEOProperties(){
SEOProperties SEO = new SEOProperties();
if (SPContext.Current != null)
{
Guid siteGuid = SPContext.Current.Site.ID;
Guid webGuid = SPContext.Current.Web.ID;
using (SPSite site = new SPSite(siteGuid))
{
using (SPWeb web = site.OpenWeb())
{
TaxonomySession session = new TaxonomySession(site);
NavigationTerm navTermino = TaxonomyNavigationContext.Current.NavigationTerm;
Term termino = navTermino.GetTaxonomyTerm(session);
var SEOPropBrowserTitle = termino.LocalCustomProperties.Where(o => o.Key == "_Sys_Seo_PropBrowserTitle").SingleOrDefault();
var SEOPropDescription = termino.LocalCustomProperties.Where(o => o.Key == "_Sys_Seo_PropDescription").SingleOrDefault();
var SEOPropKeyWords = termino.LocalCustomProperties.Where(o => o.Key == "_Sys_Seo_PropKeywords").SingleOrDefault();
var SEOPropSiteNoIndex = termino.LocalCustomProperties.Where(o => o.Key == "_Sys_Seo_PropSitemapNoIndex").SingleOrDefault();
SEO.PropBrowserDescription = SEOPropDescription.Value;
SEO.PropBrowserKeyWords = SEOPropKeyWords.Value;
SEO.PropBrowserSiteNoIndex = SEOPropSiteNoIndex.Value;
SEO.PropBrowserTitle = SEOPropBrowserTitle.Value;
}
}
}
return SEO;
}