I'm new in C# and I'm writing API test. I need to write test which will create new user. Here it is:
public async Task CreatingNewUser_Returns200()
{
string client = BaseClass.mainURL;
var json = SettingsHelper.ReadSetting("NewUser");
httpc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(BaseClass.authKey, BaseClass.authValue);
var content = new StringContent(json);
var response = await httpc.PostAsync(client, content);
Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
}
Also, I have SettingsHelper class with two methods to make my json readable:
private static JObject _jObject;
public static string ReadSetting(string name)
{
var parts = name.Split('.', StringSplitOptions.RemoveEmptyEntries);
JToken token = GetObject();
foreach (var part in parts)
{
token = token[part];
if (token == null)
{
return null;
}
}
return token.Value<string>();
}
private static JObject GetObject()
{
if (_jObject != null)
{
return _jObject;
}
var filename = Path.Combine(
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)!,
"appsettings.json");
var json = File.ReadAllText(filename);
_jObject = JObject.Parse(json);
return _jObject;
}
And I have appsettings.json file with my user:
"NewUser": {
"externalDealId": "6051",
"Id": "12312111" // and so on
}
But when I launch this test I get an error (title name). How can I fix this?
Modify the code to
public static string ReadSetting(string name)
{
var parts = name.Split('.', StringSplitOptions.RemoveEmptyEntries);
JObject jObj= GetObject();
foreach (var part in parts)
{
var token = jObj[part];
if (token == null)
{
return null;
}
else
{
return token.ToString();
}
}
return null;
}
Actually, there is still a logic which needs to be noticed var parts = name.Split('.', StringSplitOptions.RemoveEmptyEntries); may mean that support multiple setting results. But logic in the ReadSetting function is not. It only return the first setting is matched.
Related
I'm trying to use PHPickerController and access PHAsset to get file name and file size but the PHAsset are null
var config = new PHPickerConfiguration(PHPhotoLibrary.SharedPhotoLibrary) {
Filter = PHPickerFilter.ImagesFilter,
SelectionLimit = 1
};
var picker= new PHPickerViewController(config) {
ModalPresentationStyle = UIModalPresentationStyle.Popover,
Delegate = new ImagePickerDelegate((fileSize, fileName, url) => {
})
};
ViewController.PresentViewController(picker, true, null);
public class ImagePickerDelegate : PHPickerViewControllerDelegate
{
public ImagePickerDelegate(Action<int, string, string> action)
{
Action = action;
}
public Action<int, string, string> Action { get; }
public override void DidFinishPicking(PHPickerViewController picker, PHPickerResult[] results)
{
picker.DismissViewController(true, null);
foreach (var result in results)
{
var asset = PHAsset.FetchAssets(result.AssetIdentifier, null)?.firstObject as PHAsset;
// The asset are null
var fileSize = asset.ValueForKey((NSString)"fileSize");
}
}
}
As you can see in the image the request dialog show and code are not pause on following line
var asset = PHAsset.FetchAssets(result.AssetIdentifier, null)?.firstObject as PHAsset;
and return null
You could use FetchAssetsUsingLocalIdentifiers method to get PHAsset object, then it will return value.
Sample code as follows:
public override void DidFinishPicking(PHPickerViewController picker, PHPickerResult[] results)
{
picker.DismissViewController(true, null);
foreach (var result in results)
{
var refID = result.AssetIdentifier;
string[] refIDs = new string[] { refID };
var asset = PHAsset.FetchAssetsUsingLocalIdentifiers(refIDs, null)?.firstObject as PHAsset;
// var fileSize = asset.ValueForKey((NSString)"fileSize");
}
}
Also could have a look at this native code link.
I have this code which reads from my json file an array of words
public static string[] GetProfanity()
{
var json = string.Empty;
using (var fs = File.OpenRead("profanity.json"))
using (var sr = new StreamReader(fs, new UTF8Encoding(false)))
json = sr.ReadToEnd();
var profanityJson = JsonConvert.DeserializeObject<ProfanityJson>(json);
return profanityJson.badwords;
}
This is the json
{
"badwords" : ["bad", "stupid"]
}
And i try to access this here
public static bool ProfanityCheck(string inputString)
{
string[] badWords = GetProfanity();
string checkString = inputString.ToLower();
if (badWords.Any(checkString.Contains))
return true;
return false;
}
As requested I access the ProfanityCheck method here
[Command("echo")]
[Description("says whatever the user gives")]
public async Task Echo(CommandContext ctx, [RemainingText] string echoText)
{
bool hasProfanity = ProfanityFilter.ProfanityCheck(echoText);
if(hasProfanity)
{
var errMsg = ProfanityFilter.ErrorMessage();
var errSent = await ctx.Channel.SendMessageAsync(embed: errMsg).ConfigureAwait(false);
Thread.Sleep(3000);
await ctx.Channel.DeleteMessageAsync(errSent).ConfigureAwait(false);
await ctx.Channel.DeleteMessageAsync(ctx.Message).ConfigureAwait(false);
return;
}
await ctx.Channel.SendMessageAsync(echoText).ConfigureAwait(false);
}
and the struct I Deserialize it as
public struct ProfanityJson
{
[JsonProperty("badwords")]
public string[] badwords { get; private set; }
}
but when i attempt to search for this any bad words in a string I pass, nothing happens, no errors in the console, no output otherwise. I have it set up so that it sends me an error message when profanity is found, but in its current state it does nothing when profanity is passed
Your code seems to be correct... I would write the GetProfanity() in another way (and I wouldn't surely reread it every time a word is passed to to ProfanityCheck) but this is tangential to your problem. I've written a minimum testable example:
public class ProfanityJson
{
public string[] badwords { get; set; }
}
public static class ProfanityChecker
{
public static string[] GetProfanity()
{
var json = string.Empty;
using (var fs = File.OpenRead("profanity.json"))
using (var sr = new StreamReader(fs, new UTF8Encoding(false)))
json = sr.ReadToEnd();
var profanityJson = JsonConvert.DeserializeObject<ProfanityJson>(json);
return profanityJson.badwords;
}
public static string[] GetProfanity2()
{
using (var sr = new StreamReader("profanity.json"))
using (var jtr = new JsonTextReader(sr))
{
var ser = new JsonSerializer();
var profanityJson = ser.Deserialize<ProfanityJson>(jtr);
return profanityJson.badwords;
}
}
public static bool ProfanityCheck(string inputString)
{
string[] badWords = GetProfanity2();
Trace.WriteLine($"Loaded {badWords.Length} bad words");
string checkString = inputString.ToLower();
if (badWords.Any(checkString.Contains))
return true;
return false;
}
}
static void Main(string[] args)
{
Console.WriteLine(ProfanityChecker.ProfanityCheck("badder"));
}
So the only idea I have is that you are using a "stale" version of profanity.json. I've added a little loggin in the ProfanityCheck() method. It will go to the Output pane in Visual Studio.
(Would be a mess as a comment)
You could have your class like this:
public class ProfanityJson
{
[JsonProperty("badwords")]
public string[] Badwords { get; set; }
}
Is it like so? Json is case sensitive.
I'm using an xUnit test framework to write some unit test. Below is a code snippet which test if azColumns collection is empty or not. However, I was thinking is there a better way to assert azColumns collection without using two Assert inside an if..else block statement?
Maybe a one liner Assert statement that makes sense?
private static string LoadJsonFile()
{
const string fileName = "templateFileContent_1.json";
var filePath = Path.Combine(Directory.GetCurrentDirectory(), $#"Data\{fileName}");
return !File.Exists(filePath) ? string.Empty : filePath;
}
private static string GetJsonData()
{
JObject jsonObject;
var jsonFile = LoadJsonFile();
if (string.IsNullOrEmpty(jsonFile)) return string.Empty;
using (var reader = new StreamReader(jsonFile))
{
var jsonData = reader.ReadToEnd();
jsonObject = JObject.Parse(jsonData);
}
return jsonObject.ToString();
}
private static JObject GetBaseConfigurationObject()
{
var json = GetJsonData();
if (string.IsNullOrEmpty(json)) return null;
var baseObject = JsonConvert.DeserializeObject<JObject>(json);
return baseObject;
}
[Fact]
public void ExportColumns_Should_Not_Be_Empty_Or_Null()
{
// Arrange
IEnumerable<az_Columns> azColumns = null;
// Act
var baseConfig = GetBaseConfigurationObject();
var fileContent = baseConfig?["templateFileContent"];
if (fileContent != null)
{
var baseConfiguration = fileContent.ToObject<BaseConfiguration>();
azColumns = baseConfiguration?.ExportData?.az_Columns;
}
// Assert
if (azColumns == null)
{
Assert.Null(azColumns);
}
else
{
Assert.NotEmpty(azColumns);
}
}
Any inputs is greatly appreciated.
If interested in using Fluent Assertions you can assert as follows
[Fact]
public void ExportColumns_Should_Not_Be_Empty_Or_Null() {
//Arrange
//...omitted for brevity
//Act
//..omitted for brevity
//Assert
azColumns.Should().NotBeNullOrEmpty();
}
After exercising your test you are asserting that the collection should not be null or empty. If it is null or empty the test will fail otherwise it will pass as expected.
I used to work with browser-based applications. for example Angular simple repository.
function getSomeData(params) {
...
return $http({
url: conf.urlDev + 'some/rest-url',
method: "GET",
params: params,
cache: true
}).then(getDataComplete);
function getDataComplete(response) {
return response.data;
}
}
How it will look the same in c# (XAMARIN for example)?
i try :
public class BaseClient
{
protected Http _client = null;
protected string _urlObj;
protected string _basePath;
public BaseClient ()
{
_client = new Http(new HttpClientHandler());
}
public string Path
{
set
{
_urlObj = value;
}
}
public async Task<Result<IList<T>>>getList<T>(Dictionary<string,object> parametrs = null)
{
if (parametrs != null)
{
foreach(KeyValuePair<string, object> keyValue in parametrs)
{
_urlObj = _urlObj.SetQueryParam(keyValue.Key, keyValue.Value);
}
}
var response = await _client.GetAsync(_urlObj.ToString());
if (response.IsSuccessStatusCode)
{
return new Result<IList<T>>()
{
Success = true,
Value = JsonConvert.DeserializeObject<IList<T>>(await response.Content.ReadAsStringAsync())
};
}
else
{
var error = new Result<IList<T>>()
{
Error = response.StatusCode.ToString(),
Message = response.ReasonPhrase,
Success = false
};
return error;
}
}
in my service:
public async Task<IList<News>> GetAllNewsByParams(DateTime from,
string orderBy = "-published",
DateTime to = new DateTime(),
int page = 1, int category = 0)
{
_client.Path = _config.NewsPath;
var dict = new Dictionary<string, object> {
{"from", from.ToString("s")},
{"order_by", orderBy.ToString()},
{"to", to.ToString("s")},
{"page", page.ToString()}
};
if (category != 0)
{
dict.Add("category", category.ToString());
}
var res = await _client.getList<News>(dict);
return res.Value;
}
and im ny viewmodel
foreach (var item in await _newsService.GetAllNewsByParams(
_To,
_OrderBy,
_From, _Page,
selectedTag == null ? _SeletedNewsTagId : selectedTag.Id))
{
NewsList.Add(item);
}
Is his query executed synchronously ?
How do I make it an asynchronous?
First of all I would really encourage you to use RestSharp, it really simplifies making HTTP requests and deserialise them. Add a RestSharp nuget package to your project. Here is how your code will look like using RestSharp.
public class BaseClient
{
protected IRestClient _client = null;
protected string _urlObj;
protected string _basePath;
public BaseClient()
{
_client = new RestClient();
}
public async Task<Result<IList<T>>> GetList<T>(string path, Dictionary<string, object> parametrs = null)
{
var request = new RestRequest(path, Method.GET);
if (parametrs != null)
{
foreach (var keyValue in parametrs)
{
request.AddQueryParameter(keyValue.Key, keyValue.Value);
}
}
var response = await _client.Execute<List<T>>(request);
if (response.IsSuccess)
{
return new Result<IList<T>>()
{
Success = true,
Value = response.Data
};
}
else
{
var error = new Result<IList<T>>()
{
Error = response.StatusCode.ToString(),
Message = response.StatusDescription,
Success = false
};
return error;
}
}
}
In your service
public async Task<IList<News>> GetAllNewsByParams(DateTime from,
string orderBy = "-published",
DateTime to = new DateTime(),
int page = 1, int category = 0)
{
var dict = new Dictionary<string, object> {
{"from", from.ToString("s")},
{"order_by", orderBy.ToString()},
{"to", to.ToString("s")},
{"page", page.ToString()}
};
if (category != 0)
{
dict.Add("category", category.ToString());
}
var res = await _client.GetList<News>(_config.NewsPath, dict);
return res.Value;
}
And in your viewmodel
var news = await _newsService.GetAllNewsByParams(
_To,
_OrderBy,
_From, _Page,
selectedTag == null ? _SeletedNewsTagId : selectedTag.Id);
foreach (var item in news)
{
NewsList.Add(item);
}
This will be 100% asynchronous.
I am trying to set an arbitrary path in a JSON structure and I am having difficulty figuring out how to do a simple set value...
What I would like is some method like, SetValue(path,value) which operates like SelectToken, but creates the path if it does not exist and sets the value.
public void SetPreference(string username, string path, string value)
{
var prefs = GetPreferences(username);
var jprefs = JObject.Parse(prefs ?? #"{}");
var token = jprefs.SelectToken(path);
if (token != null)
{
// how to set the value of the path?
}
else
// how to add the path and value, example {"global.defaults.sort": { "true" }}
}
what I mean by global.defaults.sort path is actually { global: { defaults: { sort: { true } } } }
public string SetPreference(string username, string path, string value)
{
if (!value.StartsWith("[") && !value.StartsWith("{"))
value = string.Format("\"{0}\"", value);
var val = JObject.Parse(string.Format("{{\"x\":{0}}}", value)).SelectToken("x");
var prefs = GetPreferences(username);
var jprefs = JObject.Parse(prefs ?? #"{}");
var token = jprefs.SelectToken(path) as JValue;
if (token == null)
{
dynamic jpart = jprefs;
foreach (var part in path.Split('.'))
{
if (jpart[part] == null)
jpart.Add(new JProperty(part, new JObject()));
jpart = jpart[part];
}
jpart.Replace(val);
}
else
token.Replace(val);
SetPreferences(username, jprefs.ToString());
return jprefs.SelectToken(path).ToString();
}