Unit testing method with async - unit-testing

I am writing a unit test for a method using Moq framework.
The method calls the method Task<HttpResponseMessage> SendAsync(HttpRequestMessage request) of System.Net.Http with await.
When I execute my test case the method does not return anything. Certainly, I am doing something wrong. Please help me to find it.
Please note that this call is not loosely coupled.
I did check the other answers like Unit testing async method - test never completes which have it as loosely coupled and could be mocked.
Edit 1:
The method similar to which I am trying to unit test
class Class1
{
public async Task<string> Method(string url)
{
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get,url);
HttpResponseMessage response = await new HttpClient().SendAsync(request);
return System.Convert.ToString( response);
}
}

Are you trying to mock the HttpClient? If so this isn't the recommended approach; instead of mocking HttpClient instantiate a real HttpClient, passing a mocked HttpMessageHandler into the constructor.
Source: https://gingter.org/2018/07/26/how-to-mock-httpclient-in-your-net-c-unit-tests/
Edit: to read the contents of a HTTP response you need to call the response.Content.ReadAsStringAsync() method instead of .ToString().

Related

how to do a dependancy injection with a method in micronaut for unit testing

I have a controller class:
#Controller("/x")
class Controller {
#Get
fun index(): String {
return "test test"
}
#Post
fun dopost (userid) = executelogin(login.userId)
}
This controller depends on the executelogin method down below:
fun executelogin(userid) =
do things
If I want to write a unit test, how would I go about using a dependancy injection to introduce a version of the executelogin method. Below is what I have so far and I am not sure if I am doing it correctly:
#MicronautTest
class Controllertest(val method: executelogin()) {
#Inject
lateinit var client: RxHttpClient
#Test
fun testController(){
val request: HttpRequest<String> = HttpRequest.POST("/hello","test")
val body: String = client.toBlocking().retrieve(request)
assertNotNull(body)
assertEquals(method,method)
}
}
Above in the unit test, I am making the executelogin method a paramter for the controllertest class, which I believe is called a method injection. I was wondering if this was the correct way to go about this or if adjustments need to be made. I apologise if some of the code does not quite make sense, I am new to micronaut and the concept of dependancy injections.
If I want to write a unit test, how would I go about using a
dependancy injection to introduce a version of the executelogin
method.
You can't go about using dependency injection to introduce a version fo the executelogin method, at least not directly you can't. Micronaut doesn't support method injection.
This isn't what you asked but just as an FYI... A common thing to do would be to inject some object that contains the method that you want to call.

Unit testing against Nancy.Request.Session

I am probably missing something simple here....
I have the following method I want to unit test:
public bool In(Request request)
{
return ("Admin" == (string)request.Session["Type"]);
}
This proved less easy than I expected, because I can't find a way to properly set up a Request object to pass to the method.
Directly newing up a Request results in an object that is not session enabled, and my crude attempts with a makeshift ConfigurableBootstrapper implementation and module were quite unsuccessful.
(I found this blog post, but with no code to illustrate the explanation, I can't make much of it; I could also find no actual examples in the AppHarbify code.)
So, what would be the easiest/recommended way to get a Request object on which I can use Session?
Thanks!
Create an interface that wraps the Request. Something like..
public interface IRequestWrapper {
Session Session { get; set; }
}
The pass this interface instead of the actual implementation to the "In" method.
public bool In(IRequestWrapper request)
{
return ("Admin" == (string)request.Session["Type"]);
}
Now in your Unit Test you would create a fake implementation of IRequestWrapper that returns a Fake Session objtect?
var sut = new SomeClass();
var result = sut.In(new FakeRequest());
Of course the FakeRequest would implement IRequestWrapper and the Session object can be stubbed to return "Admin".
There are other ways to do this, for example, using a Mock/Isolation frameworks, i.e Moq
Hope this helps at least put you in the right direction.

How to unit test a synchronous method calling asynchronous method?

What is the correct way to write a unit test for a synchronous method calling async methods.
Right now my unit test are passing, but when I try to open the page, it never returns.
Why isn't my unit test failing? How can I make it fail?
I replicated my problem with this simple code:
My passing test:
[TestMethod]
public void DoSomeWork_WhenWeDoSomeWork_ShouldReturnDone()
{
var service = new SyncService();
const string expected = "Done";
var actual = service.DoSomeWork();
Assert.AreEqual(expected, actual);
}
My view that never returns:
public ActionResult Index()
{
var syncService = new SyncService();
return View((object)syncService.DoSomeWork());
}
My service that never returns to view:
public class SyncService
{
public string DoSomeWork()
{
return SomeWork().GetAwaiter().GetResult();
}
private async Task<string> SomeWork()
{
var task1 = Task.Delay(1000);
var task2 = Task.Delay(1000);
await Task.WhenAll(task1, task2);
return "Done";
}
}
I don't think I can help you with this specific example, but I think a good general strategy is to write two tests. One to test if the synchronous method passes the correct data and an other to test if the asynchronous method works properly.
I mostly work in JavaScript and that general approach works for me. Also you can check the documentation of your testing frameworks, maybe it provides some methods for this.
First, don't block on async code (link to my blog). By blocking on async code, you're actually causing a deadlock. This deadlock does not happen in your unit test because unit tests run in a thread pool context, not an ASP.NET context (link to my blog).
There are good reasons for not having synchronous wrappers for asynchronous methods. So I recommend getting rid of DoSomeWork completely, leaving only SomeWork (renamed to SomeWorkAsync).
To solve your problem, you should use asynchronous controller actions.

How do I use PowerMock / Mockito / EasyMock to use a mocked object for dependency injection?

I have an AuthenticationManager.authenticate(username,password) method that gets called in someMethod of a SomeService under test. The AuthenticationManager is injected into SomeService:
#Component
public class SomeService {
#Inject
private AuthenticationManager authenticationManager;
public void someMethod() {
authenticationManager.authenticate(username, password);
// do more stuff that I want to test
}
}
Now for the unit test I need the authenticate method to just pretend it worked correctly, in my case do nothing, so I can test if the method itself does the expected work (Authentication is tested elsewhere according to the unit testing principles, however authenticate needs to be called inside that method) So I am thinking, I need SomeService to use a mocked AuthenticationManager that will just return and do nothing else when authenticate() gets called by someMethod().
How do I do that with PowerMock (or EasyMock / Mockito, which are part of PowerMock)?
With Mockito you could just do that with this piece of code (using JUnit) :
#RunWith(MockitoJUnitRunner.class)
class SomeServiceTest {
#Mock AuthenitcationManager authenticationManager;
#InjectMocks SomeService testedService;
#Test public void the_expected_behavior() {
// given
// nothing, mock is already injected and won't do anything anyway
// or maybe set the username
// when
testService.someMethod
// then
verify(authenticationManager).authenticate(eq("user"), anyString())
}
}
And voila. If you want to have specific behavior, just use the stubbing syntax; see the documentation there.
Also please note that I used BDD keywords, which is a neat way to work / design your test and code while practicing Test Driven Development.
Hope that helps.

Mocking Spring MVC BindingResult when using annotations

I'm migrating a Spring MVC controller to use the newer style annotations, and want to unit test a controller method that validates a command object (see simple example below).
#RequestMapping(method = RequestMethod.POST)
public String doThing(Command command, BindingResult result,
HttpServletRequest request, HttpServletResponse response,
Map<String, Object> model){
ThingValidator validator = new ThingValidator();
validator.validate(command, result);
... other logic here
}
My problem is I have to call the controller's method in my unit test, and provide mock values to satisfy its signature to exercise the code properly, and I cannot work out how to mock a BindingResult.
In the old style Controller the signature simply took a HttpServletRequest and HttpServletResponse, which were easily mockable, but due to the flexibility of the new annotation style, one has to pass a lot more in via the signature.
How can one mock a Spring BindingResult for use in a unit test??
You could also use something like Mockito to create a mock of the BindingResult and pass that to your controller method, ie
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.verifyZeroInteractions;
#Test
public void createDoesNotCreateAnythingWhenTheBindingResultHasErrors() {
// Given
SomeDomainDTO dto = new SomeDomainDTO();
ModelAndView mv = new ModelAndView();
BindingResult result = mock(BindingResult.class);
when(result.hasErrors()).thenReturn(true);
// When
controller.create(dto, result, mv);
// Then
verifyZeroInteractions(lockAccessor);
}
This can give you more flexibility and simplify scaffolding.
BindingResult is an interface so can you not simply pass in one of Springs implementations of that interface?
I don't use annotations in my Spring MVC code but when I want to test the validate method of a validator I just pass in an instance of BindException and then use the values it returns in assertEquals etc.
As mentioned in this answer
A BindingResult is created for you by Spring MVC for each incoming HTTP request.
Thus, you don't want to mock the BindingResult.
Instead of calling the methods directly you should either do a real http call to the controller or perform a simulation using MockMvc.perform. Here is a tutorial on the official documentation that shows how to do it.