Quarkus. Testing with spy in the integration test - integration-testing

I see that there is some limitation when it comes to mocking/spying in Quarkus.
The question is, how would I do something similar to this with the means that Quarkus provides? To spy on restClient and see how many times it was invoked.
#QuarkusTest
public class MyResourceTest {
#Inject
#RestClient
MyRestClient restClient;
#Ineject
SomeServiceThatCallRestClient someService;
#Test
public void test() {
restClientSpy = spy(restClient);
someService.doSomething(); // it would call the restClient
assertThat(clientSpy.times(), is(equalTo(1)));
}

Related

Mock IRequestClient<> during Integration Testing using MassTransit

I'm trying to do integration testing against a MediatR Command whose handler depends on an IRequestClient injected into its constructor.
public class SayHelloCommand : IRequest<string>
{
}
public class SayHelloCommandHandler : IRequestHandler<SayHelloCommand, string>
{
private readonly IRequestClient<IGetProfileMessageResult> _profileClient;
public SayHelloCommandHandler(IRequestClient<IGetProfileMessageResult> profileClient)
{
_profileClient = profileClient;
}
public async Task<string> Handle(SayHelloCommand request, CancellationToken cancellationToken)
{
var profile = (await _profileClient.GetResponse<IGetProfileMessageResult>(new {ProfileId = 1})).Message;
return $"Hello {profile.FirstName}";
}
}
I've setup my test suite to use the InMemoryMassTransit but whenever I run my test it times out when it reaches the call using the IRequestClient<>. I've also tried to moq the IRequestClient to return a default response like this -
[Test]
public async Task ShouldSayHello()
{
var mockRequestClient = new Mock<IRequestClient<IGetProfileMessageResult>>();
mockRequestClient.Setup(x => x.GetResponse<IGetProfileMessageResult>(It.IsAny<Object>(), default, default)
.Result.Message).Returns(new GetProfileMessageResult
{
FirstName = "John"
});
serviceCollection.Add(new ServiceDescriptor(typeof(IRequestClient<IGetProfileMessageResult>), mockRequestClient.Object));
var result = await SendAsync(command);
result.Status.Should().BeFalse();
result.Message.Should().Contain("John");
}
but this still times out.
Is there a way I can set up the InMemoryMassTransit to return a default response when the requestclient is called?
You could use the in-memory test harness to setup a simple consumer that would respond to the request, instead of trying to mock IRequestClient. Though you should be able to mock it if you want, I just don’t know the syntax to properly configure your mock framework.
There are many samples using the test harness available, as well as all of the MassTransit unit tests.

Avoid HasData Seed DbContext in EF Core 2.2 during Unit Tests

In my ASP.Net CORE 2.2/EF Core 2.2 web API app, I have a HasData() method in my DbContext to seed the DB with some standard data that I use. However, I don't want to use that data when running my xUnit tests.
My unit tests use the Sqlite in-memory provider and as part of that process, it requires a call to EnsureCreated(). Well, EnsureCreated() calls OnModelCreating() which calls HasData(), so my unit test context now contains all of my HasData seed data, which I don't want. I want to seed my unit tests with different, very specific data.
Because EnsureCreated() seeds the context, and then I try adding my unit test specific seed data, I end up with both sets of data in my test DbContext and my tests fail.
How can I bypass the HasData call for my unit tests?
Instead of trying to bypass HasData(), you could instead conditionally not supply data to that method.
Quick example - if you move the pre-pop data out to e.g. "DataInitialiser" classes:
builder.HasData(new UserDataInitialiser().Data);
Then set a static flag in a base class:
public abstract class DataInitialiserControl
{
public static bool SkipInitData { get; set; } // ** flag **
}
public abstract class DataInitialiser<T> : DataInitialiserControl
{
public IList<T> Data => SkipInitData ? new List<T>() : GetData();
protected abstract IList<T> GetData();
}
Your DataInitialisers would look like this:
public class UserDataInitialiser : DataInitialiser<User>
{
protected override IList<User> GetData()
{
return new[]
{
new User {Id = 1, Name = "Bob"}
};
}
}
You could then just set the static flag in your test initialisation:
public abstract class TestBase
{
protected DbContextOptions<MyContext> DbOptions { get; private set; }
[TestInitialize]
public void InitializeDatabase()
{
// ** SKIP DATA PRE-POP **
DataInitialiserControl.SkipInitData = true;
DbOptions = BuildDbContextOptions(new DbContextOptionsBuilder<MyContext>()).Options;
using (var context = GetContext())
{
context.Database.EnsureCreated();
}
}
[TestCleanup]
public void ClearDatabase()
{
using (var context = GetContext())
{
context.Database.EnsureDeleted();
}
}
}
(Code untested, but should be more or less right).
You could always mock the call with Mock it will provides a way to mock an interface making it so the function calls of the said mocked interface will actually be calling your mocked function. This will provide a way for you to override the function call to HasData.
Of course, this means if it isn't already using an interface for that function(s) you'll have to wrap it in one.
Here are a few useful examples to Mocking: writing unit tests with NUnit and Moq and an introduction to unit testing with mocks(using moq).
I also suspect that Theory attribute and inline data could be of use to you.
Creating parameterized tests in xUnit
Hope that helps.

Why is my RestEasy WebService blocked when my #Asynchronous method is working?

I am trying to run heavy tasks asynchronously. The client then polls the server to know when the job is done. This seemed to work, but I noticed that my WebService that responds to the polling is blocked when I put a breakpoint in my #Asynchronous Method.
This is what I did:
JobWS.java // Used to start a job
#RequestScoped
#Path("/job")
#Produces(MediaType.APPLICATION_JSON)
public class JobWS {
#POST
#Path("/run/create")
public Response startJob(MyDTO dto) {
return ResponseUtil.ok(jobService.createJob(dto));
}
}
JobService.java // Creates the job in the DB, starts it and returns its ID
#Stateless
public class JobService {
#Inject
private AsyncJobService asyncJobService;
#Inject
private Worker worker;
public AsyncJob createJob(MyDTO dto) {
AsyncJob asyncJob = asyncJobService.create();
worker.doWork(asyncJob.getId(), dto);
return asyncJob; // With this, the client can poll the job with its ID
}
}
Worker.java // Working hard
#Stateless
public class Worker {
#Asynchronous
public void doWork(UUID asyncJobId, MyDTO dto) {
// Do work
// ...
// Eventually update the AsyncJob and mark it as finished
}
}
Finally, my Polling Webservice, which is the one being blocked
#RequestScoped
#Path("/polling")
#Produces(MediaType.APPLICATION_JSON)
public class PollingWS {
#Inject
AsyncJobService asyncJobService;
#GET
#Path("/{id}")
public Response loadAsyncJob(#PathParam("id") #NotNull UUID id) {
return ResponseUtil.ok(asyncJobService.loadAsyncJob(id));
}
}
If I put a breakpoint somwhere in doWork(), the PollingWS does not respond to HTTP requests anymore. When I debug through doWork(), occasionally I get a response, but only when jumping from one breakpoint to another, never when waiting at a breakpoint.
What am I missing here ? Why is my doWork() method blocking my Webservice, despite it running asynchronously ?
I found the culprit. A breakpoint suspends all threads by default. In IntelliJ, a right click on it will open the following dialog:
When changing the "Suspend" property to "Thread", my WS is not blocked anymore and everything works as expected. In retrospect, I feel a bit stupid for asking this. But hey... maybe it will help others :)

Mono: Return results from a long running method

Currently I'm beginnging with Spring + reactive programming. My aim is to return a result in a REST-endpoint from a long running method (polling on a database). I'm stuck on the api. I simply don't know how to return the result as Mono in my FooService.findFoo method.
#RestController
public class FooController {
#Autowired
private FooService fooService;
#GetMapping("/foo/{id}")
private Mono<ResponseEntity<Foo> findById(#PathVariable String id) {
return fooService.findFoo(id).map(foo -> ResponseEntity.ok(foo)) //
.defaultIfEmpty(ResponseEntity.notFound().build())
}
...
}
#Service
public class FooService {
public Mono<Foo> findFoo(String id) {
// this is the part where I'm stuck
// I want to return the results of the pollOnDatabase-method
}
private Foo pollOnDatabase(String id) {
// polling on database for a while
}
}
Use the Mono.fromSupplier method! :)
#Service
public class FooService {
public Mono<Foo> findFoo(String id) {
return Mono
.fromSupplier(() -> pollOnDatabase(id))
.subscribeOn(Schedulers.boundedElastic());
}
private Foo pollOnDatabase(String id) {
// polling on database for a while
}
}
With this method we return a Mono value ASAP, constant time with a supplier which will be evaluated on demand by the caller's subscribe. This is the non blocking way to call a long-running-blocking method.
BE AWARE that without subscription on boundedElastic the blocking pollOnDatabase method will block the original thread, which leads to thread starvation. You can find different schedules for every kind of tasks here.
DO NOT use Mono.just with long-running calculations as it will run the calculation before returning the Mono instance, thereby blocking the given thread.
+1: Watch this video to learn to avoid "reactor meltdown". Use some lib to detect blocking calls from non-blocking threads.
It's pretty simple. You could just do
#Service
public class FooService {
public Mono<Foo> findFoo(String id) {
return Mono.just(pollOnDatabase(id));
}
private Foo pollOnDatabase(String id) {
// polling on database for a while
}
}

How to Verify another method in the class was called using Moq

This seems like something simple but I can't seem to get it to work.
I have a class with a Save method that simply calls another method ShouldBeCalled(). I want to verify that if I call Save() that the other method ShouldBeCalled() is executed at least once. I thought that I could do the following.
public class ClassA
{
public virtual void Save()
{
ShouldBeCalled();
}
public virtual void ShouldBeCalled()
{
//This should get executed
}
}
[TestFixture]
public class ClassA_Test
{
[Test]
public void Save_Should_Call_ShouldBeCalled()
{
var mockClassA = new Mock<ClassA>();
mockClassA.Object.Save();
mockClassA.Verify(x => x.ShouldBeCalled(), Times.AtLeastOnce());
}
}
But I get the exception "Expected invocation on the mock at least once, but was never performed: x => x.ShouldBeCalled()"
It is just a guess but Is Moq overriding the Save() method with it's own version which ignores anything I have inside the real object's Save() method.
You are having this problem because you are mocking what you are testing. This doesn't make sense.
You are correct that Moq will replace the implementation of your method with its own. The reason is you are supposed to use Moq to mock things the class you are testing calls, not the class you are testing itself.
This test would be appropriate if your code were designed thusly:
public class ClassA
{
BusinessLogicClass bl;
public ClassA(BusinessLogicClass bl)
{
this.bl = bl;
}
public void Save()
{
bl.ShouldBeCalled();
}
}
public class BusinessLogicClass
{
public virtual void ShouldBeCalled()
{
//This should get executed
}
}
And here is the correct test of that method now:
[TestFixture]
public class ClassA_Test
{
[Test]
public void Save_ShouldCallShouldBeCalled()
{
//Arrange
var mockBLClass = new Mock<BusinessLogicClass>();
mockBLClass.Setup(x => x.ShouldBeCalled()).Verifyable();
//Act
ClassA classA = new ClassA(mockBLClass.Object);
classA.Save();
//Assert
mockBLClass.VerifyAll();
}
}
The key lesson here is that you mock/stub what your test needs to run, not what you are testing itself.
Hope this helps,
Anderson
Try using the CallBase = true and then false. I ran your code and it works.
var mockClassA = new Mock<ClassA>();
mockClassA.CallBase = true;
mockClassA.Object.Save();
mockClassA.CallBase = false;
mockClassA.Verify(x => x.ShouldBeCalled(), Times.AtLeastOnce());
Yes, this can be done. However, you need to add a line of code to have Moq track whether or not the ShouldBeCalled method was indeed called.
Something like the following will work:
var mockClassA = new Mock<ClassA>();
mockClassA.Setup(x => x.ShouldBeCalled()).Verifiable();
mockClassA.Object.Save();
mockClassA.Verify(x => s.ShouldBeCalled(), Times.AtLeastOnce());
The Setup method sets up expectations. When you call Verify, you are asking Moq to verify these expectations. If you don't make a Setup call to create expectations for the ShouldBeCalled method, then Moq doesn't consider it to be trackable and will therefore fail hard when you try to Verify it.
You can stub methods in the system under test using CallBase.
[TestFixture]
public class ClassA_Test
{
[Test]
public void Save_Should_Call_ShouldBeCalled()
{
// Arrange
var mockClassA = new Mock<ClassA>();
mockClassA.CallBase = true; // this will call real methods unless the method is mocked/stubbed.
mockClassA.Setup(a => a.ShouldBeCalled());
// Act
mockClassA.Save();
// Assert
mockClassA.Verify(a => a.ShouldBeCalled(), Times.Once());
}
}

Resources