How can I Mock async method holding CrossFilePicker? - c#

I am working on Xamarin.Forms project, that is using Autofac, Moq, and Plugin.FilePicker.
One of button commands is calling method:
private async void OnLoadFileExecute(object obj)
{
await PickUpFile();
LoadedPhrases = LoadFromFile(FileLocation);
PopulateDb(LoadedPhrases);
LoadGroups();
}
And PickUpFile() method is async:
public async Task<string> PickUpFile()
{
try
{
FileLocation = "";
var file = await CrossFilePicker.Current.PickFile();
if (file != null)
{
FileLocation = file.FilePath;
return FileLocation;
}
else
{
FileLocation = "";
return "";
}
}
catch (Exception ex)
{
Debug.WriteLine("Exception choosing file: " + ex.ToString());
return "";
}
}
I wanted to test whole command, so all methods in OnLoadFileExecute will be tested. In that case I am not sure how can I Setup PickUpFile() method to return some string. As far as I know, I can not use in the interface async methods. Correct me if I am wrong. If I could, I would be able to mock it.

You can use Task in the interface. When you mock it, you will need to return Task.FromResult

From my point of view, it should look like this
public interface IFileService {
Task<string> PickUpFile();
}
public class FileService : IFileService {
public async Task<string> PickUpFile() {
// here you have your implementation
}
}
// Here is the test method
public async Task TestTheService() {
const string fileName = "filename.txt";
var fileMocker = new Mock<IFileService>();
fileMocker.Setup( x => x.PickUpFile() ).Returns( Task.FromResult( fileName ) );
var mainClass = new MainClass( fileMocker.Object );
await mainClass.OnLoadFileExecute( null );
Assert.Equal( fileName, mainClass.FileLocation );
}
// here is the real class
public class MainClass {
private IFileService FileService { get; }
public string FileLocation { get; set; }
public MainClass( IFileService fileService ) {
FileService = fileService;
}
private async Task OnLoadFileExecute( object obj )
{
FileLocation = await FileService.PickUpFile();
LoadedPhrases = LoadFromFile( FileLocation );
PopulateDb( LoadedPhrases );
LoadGroups();
}
}

Related

How can I return especific value of a static method in my the method that I am testing?

Here is the method that I am going to test and I want IsPhoneNomValid() would return false so then I would be able to assert my expectations:
public async Task<UserResponseDto> RegisterUser(RegistrationRequestDto register, CancellationToken cancelationToken)
{
// I want the IsPhoneNomValid() method, Would return "FALSE"
var isPhoneNumberValid = register.PhoneNumber.IsPhoneNomValid();
if (!isPhoneNumberValid)
return new UserResponseDto
{
Status = new StatusMaker().ErrorStatus("Some Error Message")
};
var isActiveAccountPhoneNumberExists = await IsActiveAccountPhoneNumberExist(register.PhoneNumber, cancelationToken);
if (isActiveAccountPhoneNumberExists.Status == "error")
return new UserResponseDto
{
Status = isActiveAccountPhoneNumberExists
};
}
RegisterUser_MustReturnPhoneNumberError is my Test method:
public class AccountUserTests
{
private Mock<IUserService> _userService { get; set; }
public AccountUserTests()
{
_userService = new Mock<IUserService>();
}
public async Task RegisterUser_MustReturnPhoneNumberError()
{
//Arrang
// in here I want to setup IsPhoneNomValid() would return false.
//Act
//Assert
}
}
Is there any way that I can test the static methods which are used in my main function which I am testing ?
Here is the IsPhoneNomValid() codes:
public static class Validation
{
public static bool IsPhoneNomValid(this string phoneNumber)
{
//TODO Does it need to be foreign phone numbers ?
var isMatch = Regex.Match(phoneNumber, #"^09[0-9]{9}$");
if (isMatch.Success)
return true;
return false;
}
}
You want to test your static method IsPhoneNomValid.
[Theory]
[InlineData("123456789")]
public void TestMethod(string phoneNumber)
{
bool isPhoneNumber =Validation.IsPhoneNomValid(phoneNumber);
Assert.True(isPhoneNumber);
}
With InlineData, you can test with multiple phone numbers.
The best option is to use a really invalid phone number in your case. But I have a lib SMock that can do what you want. Here is an example of usage:
public async Task RegisterUser_MustReturnPhoneNumberError()
{
Mock.Setup(context => Validation.IsPhoneNomValid(context.It.IsAny<string>()), async () =>
{
// You must test RegisterUser method in this scope
// Here Validation.IsPhoneNomValid will always return false
var result = await RegisterUser(register, ct);
Assert.AreEqual(expectedStatus, result.Status);
}).Returns(false);
}

not able to await a casted method call - syntax error

I'm trying to await SubscribeToKlineUpdatesAsync, which is being casted from IExchangeClient to BinanceSpotClient, but it doesn't let me do it. The following error message appears:
The name 'await' does not exist in the current context
What is the correct syntax to do that?
public class BinanceSpotClient : IExchangeClient
{
...
public async Task<CallResult<UpdateSubscription>> SubscribeToKlineUpdatesAsync(string symbol, TimeFrame timeFrame, Action<IBinanceStreamKlineData> callback)
{
return await _socketClient.Spot.SubscribeToKlineUpdatesAsync(symbol, timeFrame.ToKlineInterval(), callback);
}
}
public class LiveTradeManager : ITradeManager
{
private static readonly ILog _logger = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private readonly IExchangeClient _exchangeClient;
private readonly TradeOptions _tradeOptions;
public LiveTradeManager(IExchangeClient exchangeClient, TradeOptions tradeOptions)
{
_exchangeClient = exchangeClient;
_tradeOptions = tradeOptions;
}
public void Run()
{
try
{
var strategy = StrategyUtils.GetStrategyByName("RsiStrategy");
var result = await (_exchangeClient as BinanceSpotClient).SubscribeToKlineUpdatesAsync(_tradeOptions.Pair, strategy.TimeFrame, data => // the error appears here
{
});
if (result.Success)
{
result.Data.ConnectionLost += () =>
{
_logger.Error("Connection lost.");
};
result.Data.ConnectionRestored += (e) =>
{
_logger.Info("Connection was restored.");
};
}
}
catch (Exception ex)
{
_logger.Error($"{ex.Message} | Stack trace: {ex.StackTrace}");
}
}
}
Change the signature of the Run method to be async and return Task (most likely change of ITradeManager also required):
public async Task Run()
{
// you can use await here
}

I'm getting Http error 404 as a result on working on abp.io framework

I'm new at working on the abp.io framework, precisely Angular + Entity Framework Core.
I want to be able to create or display an objects list of a class that I've created.
For example, I've made a class called Address on the Domain layer.
Here is its AppService on the Application layer:
namespace ASKOM.RefPlusStudio.core.Services
{
[Authorize(corePermissions.Addresses.Default)]
public class AddressAppService : coreAppService, IAddressAppService
{
private readonly IAddressRepository _addressRepository;
private readonly AddressManager _addressManager;
public AddressAppService(IAddressRepository addressRepository, AddressManager addressManager)
{
_addressRepository = addressRepository;
_addressManager = addressManager;
}
[Authorize(corePermissions.Addresses.Create)]
public async Task<AddressDto> CreateAsync(CreateUpdateAddressDto input)
{
var address = await _addressManager.CreateAsync(
input.StreetNumber,
input.StreetName,
input.PostalCode,
input.City,
input.Country
);
await _addressRepository.InsertAsync(address);
return ObjectMapper.Map<Address, AddressDto>(address);
}
[Authorize(corePermissions.Addresses.Delete)]
public async Task DeleteAsync(Guid id)
{
await _addressRepository.DeleteAsync(id);
}
public async Task<AddressDto> GetAsync(Guid id)
{
var address = await _addressRepository.GetAsync(id);
return ObjectMapper.Map<Address, AddressDto>(address);
}
public async Task<PagedResultDto<AddressDto>> GetListAsync(GetAddressListDto input)
{
if (input.Sorting.IsNullOrWhiteSpace())
{
input.Sorting = nameof(Address.Country);
}
var addresses = await _addressRepository.GetListAsync(
input.SkipCount,
input.MaxResultCount,
input.Sorting,
input.Filter
);
var totalCount = await AsyncExecuter.CountAsync(
_addressRepository.WhereIf(
!input.Filter.IsNullOrWhiteSpace(),
address => address.Country.Contains(input.Filter)
)
);
return new PagedResultDto<AddressDto>(
totalCount,
ObjectMapper.Map<List<Address>, List<AddressDto>>(addresses)
);
}
[Authorize(corePermissions.Addresses.Edit)]
public async Task UpdateAsync(Guid id, CreateUpdateAddressDto input)
{
var address = await _addressRepository.GetAsync(id);
address.StreetNumber = input.StreetNumber;
address.StreetName = input.StreetName;
address.PostalCode = input.PostalCode;
address.City = input.City;
address.Country = input.Country;
await _addressRepository.UpdateAsync(address);
}
}
}
I gave them all the permissions needed.
Here is corePermissions.cs :
namespace ASKOM.RefPlusStudio.core.Permissions
{
public static class corePermissions
{
public const string GroupName = "core";
//Add your own permission names. Example:
//public const string MyPermission1 = GroupName + ".MyPermission1";
public static class Addresses
{
public const string Default = GroupName + ".Addresses";
public const string Create = Default + ".Create";
public const string Edit = Default + ".Edit";
public const string Delete = Default + ".Delete";
}
}
}
I wanted to see if it can display an Addresses list so I've made a static one on DataSeeder:
namespace ASKOM.RefPlusStudio.core
{
public class coreDataSeederContributor : IDataSeedContributor, ITransientDependency
{
private readonly IRepository<Address, Guid> _addressRepository;
private readonly IGuidGenerator _guidGenerator;
public coreDataSeederContributor(IRepository<Address, Guid> addressRepository, IGuidGenerator guidGenerator)
{
_addressRepository = addressRepository;
_guidGenerator = guidGenerator;
}
public async Task SeedAsync(DataSeedContext context)
{
if (await _addressRepository.GetCountAsync() > 0)
{
return;
}
var address = new Address(
id: _guidGenerator.Create(),
streetNumber: 07,
streetName: "Med Salah Belhaj",
postalCode: 2080,
city: "Ariana",
country: "Tunisie"
);
//autoSave: true
await _addressRepository.InsertAsync(address);
}
}
}
Here is now the result on Swagger UI:
When I try to open the request URL, here is what it shows:
I'm sure that I may have forgotten something and that's why I get Access Denied on the Request URL, but I don't really know what it is because I'm new at this.
Could you please help me?
Thank you
There was a problem with the database. That's why it hasn't read the data I've provided in the DataSeedProvider.

How to call a method inside Execute method in Quartz.net Scheduler

I am a beginner to Quartz.Net. I am trying to call a method from my quartz.net schedule job excute method. Can anyone help if this is the right way or is there any better approach available?
[HttpPost]
public ActionResult Index(Tweet twts, HttpPostedFileBase imgFile)
{
UploadFile uploadFile = new UploadFile();
bool isPosted = uploadFile.UploadFiles(twts, imgFile);
if(isPosted)
{
twts.tweets = "";
ViewBag.Message = "Tweeted Successfully";
}
else
{
ViewBag.Message = "Tweet Post Unsuccessful";
}
return View("Tweets");
}
UploadFile.cs
public bool UploadFiles(Tweet twts, HttpPostedFileBase imgFile)
{
string key = Utils.Twitterkey;
string secret = Utils.Twittersecret;
string token = Utils.Twittertoken;
string tokenSecret = Utils.TwittertokenSecret;
string message = twts.tweets;
string filePath; string imagePath = "";
HttpPostedFileBase filebase =
new HttpPostedFileWrapper(HttpContext.Current.Request.Files["imgFile"]);
if (imgFile == null)
{
imgFile = filebase;
}
if (imgFile.FileName != "")
{
filePath = HttpContext.Current.Server.MapPath("~/Images/");
if (!Directory.Exists(filePath))
{
Directory.CreateDirectory(filePath);
}
filePath = filePath + Path.GetFileName(imgFile.FileName);
imgFile.SaveAs(filePath);
imagePath =
Path.Combine(HttpContext.Current.Server.MapPath(#"~/Images/"), filePath);
}
//Enter the Image Path if you want to upload image.
var service = new TweetSharp.TwitterService(key, secret);
service.AuthenticateWith(token, tokenSecret);
//this Condition will check weather you want to upload a image & text or only text
if (imagePath.Length > 0)
{
using (var stream = new FileStream(imagePath, FileMode.Open))
{
var result = service.SendTweetWithMedia(
new SendTweetWithMediaOptions
{
Status = message,
Images = new Dictionary<string, Stream> { { "sos", stream } }
});
}
}
else // just message
{
var result = service.SendTweet(new SendTweetOptions
{
Status = message
});
}
return true;
}
JobScheduler.cs
public class JobScheduler<IDGJob>
where IDGJob : Quartz.IJob
{
public static void Start()
{
IScheduler scheduler = StdSchedulerFactory.GetDefaultScheduler().Result;
scheduler.Start();
IJobDetail job = JobBuilder.Create<IDGJob>().Build();
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("IDGJob", "IDG")
.WithCronSchedule("0 0 12 1/1 * ? *")
.StartAt(DateTime.UtcNow)
.WithPriority(1)
.Build();
scheduler.ScheduleJob(job, trigger);
}
}
IDGJob.cs
public class IDGJob : IJob
{
Action<Tweet, HttpPostedFileBase> upFile;
public IDGJob(Action<Tweet, HttpPostedFileBase> UploadFiles)
{
if (UploadFiles == null)
{
throw new ArgumentNullException(nameof(UploadFiles));
}
Action<Tweet, HttpPostedFileBase> upFile = UploadFiles;
}
public void Execute(IJobExecutionContext context)
{
upFile(twts, imgFile); ****
}
}
Based on the below answer I updated this class.
**** Throws Error "The twts does not exist in the current context".. of course it will, but my question how to pass the value from the above flow?
Your IDGJob type should take a callback and invoke it inside Execute()
public class IDGJob : IJob
{
Action callback;
public IDGJob(Action action)
{
if(action == null)
throw new ArgumentNullException(nameof(action));
callback = action;
}
public void Execute(IJobExecutionContext context)
{
callback();
}
}
Now the code using this class can provide a callback when it constructs an object and have it do whatever is needed.
Alternatively, you can expose an event Executed and bind handlers in the client code.
public class IDGJob : IJob
{
public event EventHandler Executed;
public void Execute(IJobExecutionContext context)
{
Executed?.(this, EventArgs.Empty);
}
}
In this version, client code would += on Executed.

C# design guideline - calling appropriate method based on string value

Looking for design guidelines for the following problem.
I'm receiving two string values - action and message and have to call appropriate method which processes string message (processM1MessageVer1, processM1MessageVer2, processM2MessageVer1...). The method I have to call depends on the given string action. There are 2 versions (but in future there might be more) of each processing method. The version of method I have to call is determined by global variable version. Every method returns object of different type (ResultObject1, ResultObject2...). The result has to be serialized, converted to base64 and returned back.
Is there more elegant way of writing this (eliminate duplicate code, make possible future changes easier, reduce code...):
string usingVersion = "ver1";
public string processRequest(string action, string message)
if (usingVersion == "ver1"){
processRequestVer1(action, message);
}
else{
processRequestVer2(action, message);
}
}
//version 1
public string processRequestVer1(string action, string message){
string result = "";
switch (action){
case "m1":
ResultObject1 ro = processM1MessageVer1(message);
result = serialize(ro);
result = convertToB64(result);
case "m2":
ResultObject2 ro = processM2MessageVer1(message);
result = serialize(ro);
result = convertToB64(result);
case "m3":
ResultObject3 ro = processM3MessageVer1(message);
result = serialize(ro);
result = convertToB64(result);
}
return result;
}
//version 2
public string processRequestVer2(string action, string message){
string result = "";
switch (action){
case "m1":
ResultObject1 ro = processM1MessageVer2(message);
result = serialize(ro);
result = convertToB64(result);
case "m2":
ResultObject2 ro = processM2MessageVer2(message);
result = serialize(ro);
result = convertToB64(result);
case "m3":
ResultObject3 ro = processM3MessageVer2(message);
result = serialize(ro);
result = convertToB64(result);
}
return result;
}
It would be simplier if messages that have to be processed are of different object types instead of strings so that appropriate method could be called polymorphically. The fact that every process method returns different object type also complicates things even more. But these don't depend on me and I cannot change it.
My approach (make it more object oriented, and you should justify whether it's appropriate to create class structure depending on how complex your processing logic is. If your processing logic is only little then maybe this is over-engineering):
For serialize and convert to base 64, I assume you have some logic to do those tasks in a generic way. If not, move those to sub class also
public interface IRequestProcessorFactory
{
IRequestProcessor GetProcessor(string action);
}
public class FactoryVersion1 : IRequestProcessorFactory
{
public IRequestProcessor GetProcessor(string action)
{
switch(action)
{
case "m1":
return new M1Ver1RequestProcessor();
case "m2":
return new M2Ver1RequestProcessor();
case "m3":
return new M3Ver1RequestProcessor();
default:
throw new NotSupportedException();
}
}
}
public class FactoryVersion2 : IRequestProcessorFactory
{
public IRequestProcessor GetProcessor(string action)
{
switch(action)
{
case "m1":
return new M1Ver2RequestProcessor();
case "m2":
return new M2Ver2RequestProcessor();
case "m3":
return new M3Ver2RequestProcessor();
default:
throw new NotSupportedException();
}
}
}
public interface IRequestProcessor
{
string ProcessRequest(string message);
}
public class RequestProcessorBase<T>
{
public string ProcessRequest(string message)
{
T result = Process(message);
string serializedResult = Serialize(result);
return ConvertToB64(serializedResult);
}
protected abstract T Process(string message);
private string Serialize(T result)
{
//Serialize
}
private string ConvertToB64(string serializedResult)
{
//Convert
}
}
public class M1Ver1RequestProcessor : RequestProcessorBase<ResultObject1>
{
protected ResultObject1 Process(string message)
{
//processing
}
}
public class M2Ver1RequestProcessor : RequestProcessorBase<ResultObject2>
{
protected ResultObject2 Process(string message)
{
//processing
}
}
public class M3Ver1RequestProcessor : RequestProcessorBase<ResultObject3>
{
protected ResultObject3 Process(string message)
{
//processing
}
}
public class M1Ver2RequestProcessor : RequestProcessorBase<ResultObject1>
{
protected ResultObject1 Process(string message)
{
//processing
}
}
public class M2Ver2RequestProcessor : RequestProcessorBase<ResultObject2>
{
protected ResultObject2 Process(string message)
{
//processing
}
}
public class M3Ver2RequestProcessor : RequestProcessorBase<ResultObject3>
{
protected ResultObject3 Process(string message)
{
//processing
}
}
Usage:
string action = "...";
string message = "...";
IRequestProcessorFactory factory = new FactoryVersion1();
IRequestProcessor processor = factory.GetProcessor(action);
string result = processor.ProcessRequest(message);
The switch is still there in factory class, but it only returns processor and doesn't do actual work so it's fine for me
First - define interface that suit you best, like this
public interface IProcessMessage
{
string ActionVersion { get; }
string AlgorithmVersion { get; }
string ProcessMessage(string message);
}
Then create as many implementation as you need
public class processorM1Ver1 : IProcessMessage
{
public string ProcessMessage(string message)
{
ResultObject1 ro1 = processM1MessageVer1(message);
var result = serialize(ro1);
result = convertToB64(result);
return result;
}
public string ActionVersion {get { return "m1"; }}
public string AlgorithmVersion {get { return "ver1"; }}
}
public class processorM2Ver1 : IProcessMessage
{
public string ActionVersion {get { return "m2"; }}
public string AlgorithmVersion {get { return "ver1"; }}
public string ProcessMessage(string message)
{
ResultObject1 ro1 = processM2MessageVer1(message);
var result = serialize(ro1);
result = convertToB64(result);
return result;
}
}
public class processorM1Ver2 : IProcessMessage
{
public string ActionVersion {get { return "m1"; }}
public string AlgorithmVersion {get { return "ver2"; }}
public string ProcessMessage(string message)
{
ResultObject1 ro1 = processM1MessageVer2(message);
var result = serialize(ro1);
result = convertToB64(result);
return result;
}
}
Now you need something that know which implementation is best in current context
public class MessageProcessorFactory
{
private MessageProcessorFactory() { }
private static readonly MessageProcessorFactory _instance = new MessageProcessorFactory();
public static MessageProcessorFactory Instance { get { return _instance; }}
private IEnumerable<IProcessMessage> _processorCollection;
IEnumerable<IProcessMessage> ProcessorCollection
{
get
{
if (_processorCollection == null)
{
//use reflection to find all imlementation of IProcessMessage
//or initialize it manualy
_processorCollection = new List<IProcessMessage>()
{
new processorM1Ver1(),
new processorM2Ver1(),
new processorM1Ver2()
};
}
return _processorCollection;
}
}
internal IProcessMessage GetProcessor(string action)
{
var algorithVersion = ReadAlgorithVersion();
var processor = ProcessorCollection.FirstOrDefault(x => x.AlgorithmVersion == algorithVersion && x.ActionVersion == action);
return processor;
}
private string ReadAlgorithVersion()
{
//read from config file
//or from database
//or where this info it is kept
return "ver1";
}
}
It can be use in such way
public class Client
{
public string ProcessRequest(string action, string message)
{
IProcessMessage processor = MessageProcessorFactory.Instance.GetProcessor(action);
return processor.ProcessMessage(message);
}
}

Categories

Resources