Nethereum C# Unit Test GetTransactionCount - c#

Nethereum uses an Async method to get the TransactionCount of an address.
I have put the method into a async task:
public async Task<object> GetTxCount(string address)
{
return await web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(address).ConfigureAwait(false);
}
And attempting to test it with...
[TestMethod]
public async Task TestMethodAsync()
{
string address = "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae";
EthTest.Eth et = new EthTest.Eth();
var encoded = et.GetTxCount(address);
encoded.Wait();
}
How should I call the GetTxCount from a unit test to get the actual result.
I have used the "wait" command even though it is not recommended, but still cannot get it to return a result.
The Unit test bombs out - it does not even hit the API that Nethereum calls.

You have already made the test async then use async all the way through by using await to call GetTxCount
[TestMethod]
public async Task TestMethodAsync() {
string address = "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae";
var et = new EthTest.Eth();
var encoded = await et.GetTxCount(address);
}
Given that GetTxCount is just returning the task then there really is no need to await it in the method.
Refactor to
public Task<HexBigInteger> GetTxCount(string address) {
return web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(address);
}
or
public async Task<HexBigInteger> GetTxCount(string address) {
var result = await web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(address).ConfigureAwait(false);
return result.
}
Reference Async/Await - Best Practices in Asynchronous Programming

Related

Mock unit test async task setup returning null

I have a TestMethod async task that is mocking a service setup with ReturnsAsync but for some reason the result keeps returning null.
[TestMethod]
public async Task GetCustomerAsync_Returns_CustomerResults()
{
var customerResults = _fixture.Create<CustomerResults>();
_mockCustomerService.Setup(s => s.GetCustomerAsync(1)).ReturnsAsync(customerResults);
var result = await _customerManager.GetCustomerDetails(1);
Asset.IsNotNull(result);
}
public async Task<CustomerResults> GetCustomerDetails(int id)
{
var results = await _customerService.GetCustomerAsync(id);
return results;
}
You should have posted all the code needed to understand the problem, the creation of _mockCustomerService and _fixture variable, etc.
Having said that i can probably make a guess that you are creating the mockerService and not 'Frezzing' it. The call to _customerManager is not using the _mockCustomerService that you want it to use. You can read about this here AutoFixture Freeze

Calling non-async methods

Have a class library that makes use of a DbContext to return results from sql.
If I want to build a
Class library method that might take a few seconds. This class is injected into an asp.net core webapp in its Startup
class Util
{
public string DoStuff(string colorVal) {
string ourValue = (from a in ctx.BigTable where a.color == colorVal select a.DoneFlag).FirstOrDefault();
return ourValue;
}
}
Do I need to make this method async also if I intend to use it from code like this
Web project
Util o;
public async Task<IViewComponentResult> InvokeAsync()
{
var item = await GetMatchingColorAsync();
return View(item);
}
private Task<string> GetMatchingColorAsync()
{
string matchingColor = o.DoStuff("red");
return Task.FromResult(matchingColor);
}
Ideally yes. You could even use FirstOrDefaultAsync while you're at it (depending on what your underlying data source is):
public async Task<string> DoStuff(string colorVal) {
string ourValue = await (from a in ctx.BigTable where a.color == colorVal select a.DoneFlag).FirstOrDefaultAsync();
var someColor = await GetMatchingColorAsync();
return ourValue;
}
Microsoft has a series of articles about Asynchronous programming with async and await that are quite well written. They're worth the read.
If you absolutely can't change the calling methods, then you could just synchronously wait:
public string DoStuff(string colorVal) {
string ourValue = (from a in ctx.BigTable where a.color == colorVal select a.DoneFlag).FirstOrDefault();
var someColor = GetMatchingColorAsync().GetAwaiter().GetResult();
return ourValue;
}
Easy right? Except it blocks the thread (you lose the benefit of the asynchronous methods) and you risk deadlocking, as explained in this article: Don't Block on Async Code.
That's Bad™

FakeItEasy - Is it possible to test constraints asynchronously (i.e. MatchesAsync)?

I've run into difficulty testing System.Net.Http.HttpClient with FakeItEasy. Consider this scenario:
//Service that consumes HttpClient
public class LoggingService
{
private readonly HttpClient _client;
public LoggingService(HttpClient client)
{
_client = client;
_client.BaseAddress = new Uri("http://www.example.com");
}
public async Task Log(LogEntry logEntry)
{
var json = JsonConvert.SerializeObject(logEntry);
var httpContent = new StringContent(json, Encoding.UTF8, "application/json");
await _client.PostAsync("/api/logging", httpContent);
}
}
public class LogEntry
{
public string MessageText { get; set; }
public DateTime DateLogged { get; set; }
}
Unit Testing
From a unit testing perspective, I want to verify that HttpClient posts the specified logEntry payload to the appropriate URL (http://www.example.com/api/logging). (Side Note: I can't test the HttpClient.PostAsync() method directly because my service uses the concrete implementation of HttpClient and Microsoft does not provide an interface for it. However, I can create my own HttpClient that uses a FakeMessageHandler (below) as a dependency, and inject that into the service for testing purposes. From there, I can test DoSendAsync()
//Helper class for mocking the MessageHandler dependency of HttpClient
public abstract class FakeMessageHandler : HttpMessageHandler
{
protected sealed override Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
return DoSendAsync(request);
}
public abstract Task<HttpResponseMessage> DoSendAsync(HttpRequestMessage request);
}
In theory, I should be able to use the Matches() method in FakeItEasy to write a custom matching function. This would look something like this:
//NUnit Test
[TestFixture]
public class LoggingServiceTests
{
private LoggingService _loggingService;
private FakeMessageHandler _fakeMessageHandler;
private HttpClient _httpClient;
[SetUp]
public void SetUp()
{
_fakeMessageHandler = A.Fake<FakeMessageHandler>();
_httpClient = new HttpClient(_fakeMessageHandler);
_loggingService = new LoggingService(_httpClient);
}
[Test]
public async Task Logs_Error_Successfully()
{
var dateTime = new DateTime(2016, 11, 3);
var logEntry = new LogEntry
{
MessageText = "Fake Message",
DateLogged = dateTime
};
await _loggingService.Log(logEntry);
A.CallTo(() => _fakeMessageHandler.DoSendAsync(
A<HttpRequestMessage>.That.Matches(
m => DoesLogEntryMatch("Fake Message", dateTime, HttpMethod.Post,
"https://www.example.com/api/logging", m)))
).MustHaveHappenedOnceExactly();
}
private bool DoesLogEntryMatch(string expectedMessageText, DateTime expectedDateLogged,
HttpMethod expectedMethod, string expectedUrl, HttpRequestMessage actualMessage)
{
//TODO: still need to check expectedMessageText and expectedDateLogged from the HttpRequestMessage content
return actualMessage.Method == expectedMethod && actualMessage.RequestUri.ToString() == expectedUrl;
}
}
Checking the URL and the HttpMethod is easy enough (as demonstrated above). But, in order to check the payload, I need to check the content of the HttpRequestMessage. Here's where it gets tricky. The only way I've found to read the content of an HttpRequestMessage is to use one of the built-in async methods (i.e. ReadAsStringAsync, ReadAsByteArrayAsync, ReadAsStreamAsync, etc.) As far as I can tell, FakeItEasy does not support async/await operations inside of the Matches() predicate. Here's what I tried:
Convert DoesLogEntryMatch() method to async, and await the ReadAsStringAsync() call (DOES NOT WORK)
//Compiler error - Cannot convert async lambda expression to delegate type 'Func<HttpRequestMessage, bool>'.
//An async lambda expression may return void, Task or Task<T>,
//none of which are convertible to 'Func<HttpRequestMessage, bool>'
A.CallTo(() => _fakeMessageHandler.DoSendAsync(
A<HttpRequestMessage>.That.Matches(
async m => await DoesLogEntryMatch("Fake Message", dateTime, HttpMethod.Post,
"http://www.example.com/api/logging", m)))
).MustHaveHappenedOnceExactly();
private async Task<bool> DoesLogEntryMatch(string expectedMessageText, DateTime expectedDateLogged,
HttpMethod expectedMethod, string expectedUrl, HttpRequestMessage actualMessage)
{
var message = await actualMessage.Content.ReadAsStringAsync();
var logEntry = JsonConvert.DeserializeObject<LogEntry>(message);
return logEntry.MessageText == expectedMessageText &&
logEntry.DateLogged == expectedDateLogged &&
actualMessage.Method == expectedMethod && actualMessage.RequestUri.ToString() == expectedUrl;
}
Leave DoesLogEntryMatch as a non-async method, and don't await ReadAsStringAsync(). This seems to work when I tested it, but I have read that doing this could cause deadlocks in certain situations.
private bool DoesLogEntryMatch(string expectedMessageText, DateTime expectedDateLogged,
HttpMethod expectedMethod, string expectedUrl, HttpRequestMessage actualMessage)
{
var message = actualMessage.Content.ReadAsStringAsync().Result;
var logEntry = JsonConvert.DeserializeObject<LogEntry>(message);
return logEntry.MessageText == expectedMessageText &&
logEntry.DateLogged == expectedDateLogged &&
actualMessage.Method == expectedMethod && actualMessage.RequestUri.ToString() == expectedUrl;
}
Leave DoesLogEntryMatch as a non-async method, and await ReadAsStringAsync() inside of a Task.Run(). This spawns a new thread that will await the result, but allows the original method call to run synchronously. From what I've read, this is the only "safe" way to call an asynchronous method from a synchronous context (i.e. no deadlocks). This is what I wound up doing.
private bool DoesLogEntryMatch(string expectedMessageText, DateTime expectedDateLogged,
HttpMethod expectedMethod, string expectedUrl, HttpRequestMessage actualMessage)
{
var message = Task.Run(async () => await actualMessage.Content.ReadAsStringAsync()).Result;
var logEntry = JsonConvert.DeserializeObject<LogEntry>(message);
return logEntry.MessageText == expectedMessageText &&
logEntry.DateLogged == expectedDateLogged &&
actualMessage.Method == expectedMethod && actualMessage.RequestUri.ToString() == expectedUrl;
}
So, I got this working, but it seems like there should be a better way of doing this in FakeItEasy. Is there something equivalent to a MatchesAsync() method that would take a predicate that supports async/await?
There's no MatchesAsync in FakeItEasy; maybe it's something that could be added (though of course it could only work for async methods).
Leave DoesLogEntryMatch as a non-async method, and don't await ReadAsStringAsync(). This seems to work when I tested it, but I have read that doing this could cause deadlocks in certain situations.
In fact, I think that's the correct approach here. Using .Wait() or .Result is strongly discouraged in application code, but you're not in application code, you're in a unit test. The deadlock that can occur is caused by the presence of a SynchronizationContext, which exists in some frameworks (desktop frameworks like WPF or WinForms, classic ASP.NET), but not in the context of a unit test, so you should be fine. I used the same approach successfully in the past.

Non async method, call async method, and need to work with the result

I have a syncronized method and class which is static. I have to call Mandrill and use the result.
My method, looks like this
public static void MyMethod(Association association , Person p)
{
MandrillApi mandrill = new MandrillApi(mandrillAPIKey);
var mail = GetMandrillMessage(fromEmail, clubAdmin.ProfileInfo.Email);
mail.AddGlobalVariable("Key", value);
mail.AddGlobalVariable("Key", value);
mail.AddGlobalVariable("AssociationBaseUrl", SettingsHelper.GetSetting("AssociationBaseUrl"));
mail.AddGlobalVariable("Key", value);
mail.AddGlobalVariable("UserFirstname", clubAdmin.Firstname);
mail.Subject = "Subject goes here";
var messageRequest = new SendMessageTemplateRequest(mail, "template");
var result = mandrill.SendMessageTemplate(messageRequest);
}
I need result.Result. I can't make my method to async.
So is there any way to get result.Result and use it in a new method?
i was thinking to do something like
var messageRequest = new SendMessageTemplateRequest(mail, "template");
var result = mandrill.SendMessageTemplate(messageRequest);
CallMyMethod(result.Result.First().Id)
but this wont work, it will just stop the program. Really need help. Ask for more information. I am really bad at explaining myself.
You are experiencing a deadlock. The correct wait to call asynchronous code from synchronous code is to make your whole call stack (starting at the controller's action method) asynchronous. IMO not doing this is an unreasonable constraint.
Changes:
Make MyMethod return Task instead of void so it can be awaited
Add async to MyMethod
Add await to wait for the result from IMandrilApi.SendMessageTemplate
Rename MyMethod to MyMethodAsync, not required but it follows a commonly accepted naming convention
Make controller method async and return a Task. If the controller is returning something then return Task<T> where T is the current return type.
Controller method awaits the result of MyMethodAsync
public static async Task MyMethodAsync(Association association , Person p)
{
/* your existing code has been removed for brevity as there are no changes in that code */
var result = await mandrill.SendMessageTemplate(messageRequest);
}
Controller method
I had to make an assumption this code but you did state in the comments the call stack is controller → MyMethod. Also note that only the relevant part to the question is shown and I had no other info to go on.
[HttpPost]
public async Task SendMessage()
{
await MyMethodAsync(association, person);
}
You can put your method to a Task and await it
public static object MyMethod(Association association , Person p)
{
MandrillApi mandrill = new MandrillApi(mandrillAPIKey);
var mail = GetMandrillMessage(fromEmail, clubAdmin.ProfileInfo.Email);
mail.AddGlobalVariable("Key", value);
mail.AddGlobalVariable("Key", value);
mail.AddGlobalVariable("AssociationBaseUrl", SettingsHelper.GetSetting("AssociationBaseUrl"));
mail.AddGlobalVariable("Key", value);
mail.AddGlobalVariable("UserFirstname", clubAdmin.Firstname);
mail.Subject = "Subject goes here";
var messageRequest = new SendMessageTemplateRequest(mail, "template");
var result = mandrill.SendMessageTemplate(messageRequest);
return result;
}
[HttpPost]
public async Task<HttpResponseMessage> Post([FromBody]MyObject obj)
{
var task = Task.Run(() => MyMethod(a,p));
var result = await task;
return Request.CreateResponse(...);
}
But async in the controller does not make the user experience async. User will have to wait as long as task finishes. So why do we do async ?

Is async keyword necessary in the method signature when calling another async method internally?

Here's a C# async code snippet. Is GetAsync the same as GetAsync2? Is GetAsync a right implementation?
public Task<IHttpActionResult> GetAsync()
{
return GetOneAsync();
}
public async Task<IHttpActionResult> GetAsync2()
{
return await GetOneAsync();
}
private async Task<IHttpActionResult> GetOneAsync()
{
using (var httpClient = new HttpClient())
{
await httpClient.GetAsync("http://baidu.com");
}
return Ok();
}
It is not the same. GetAsync does not generate a state machine and does not wait for the result of GetOneAsync, which is the preferred option when the result of the async method is not needed in this method.
The resulting code is more efficient as well as no state machine is generated and no context switch is required.
See Understanding the cost of Async/Await article for more info.

Categories

Resources