Mocking a static method which is written in Scala in Java Unit test - scala

We are using Kafka Clients in a project.
I am trying to mock a static method from the Kafka client via JMockit :
new NonStrictExpectations() {
{
new MockUp<Consumer>()
{
#Mock
ConsumerConnector createJavaConsumerConnector(
ConsumerConfig c){
return null;
}
};
}
};
Looks like JMockit is not working due to some reason. I am sure of the syntax of JMockit for mocking static methods. This is the error :
java.lang.IllegalArgumentException: Matching real methods not found for the following mocks:
dispatcher.DispatcherTests$1$1#createJavaConsumerConnector(kafka.consumer.ConsumerConfig)
If this does not work because the Kafka client code is in Scala, how does my program work?

There are multiple ConsumerConnector classes - the one I was using was from the wrong package..Scala was not creating any problem here. It worked after using the right ConsumerConnector class.

Related

Should I create a static Vertx instance for an object in a Vertx application?

I'm using vertx in my project nad I guess that I had a terrible idea when I create a Java class like this
public class MyClass {
static Vertx vertx = Vertx.vertx();
public void run() {
vertx.getOrCreateContext().runOnContext(event -> {
// run something
});
}
}
Everything I run in this run() function will be run asynchronous but I'm not sure that it's recommended.
Well, if you have a vert.x application, you can get the Vertx object in a class by extending the AbstractVerticle and getting the vert.x object from it using the getVertx() method.
Also, Vertx.vertx() always creates a new instance. It's better to use something like Vertx.currentContext().getOwner()
Remember that static objects are created before non-static objects and non-static methods being run. This means that if there are some configs/checks that needs to be done at bootstrap (for example metrics), they could be missed, unless maybe also done in a static context.
I would advice against doing this. The reason is, that it would heaviliy reduce your ability to write tests for all the classes that rely on that static Vertx instance.
Use dependency injection instead (or use Verticles as described in the other answer).

Bean not found for topic name when using BinderAwareChannelResolver

I am using BinderAwareChannelResolver to publish messages to dynamic topics.
Its throwing Failed to find MessageChannel bean with name 'topic-name'.
Anyways, BinderAwareChannelResolver is deprecated in the 3.0:
https://github.com/spring-cloud/spring-cloud-stream#notable-deprecations
The BinderAwareChannelResolver is deprecated in favor if providing spring.cloud.stream.sendto.destination property. This is primarily for function-based programming model. For StreamListener it would still be required and thus will stay until we deprecate and eventually discontinue StreamListener and annotation-based programming model.
So you should use sendto.destination property, you have mor info in the docs:
https://cloud.spring.io/spring-cloud-static/spring-cloud-stream/3.0.3.RELEASE/reference/html/spring-cloud-stream.html#_spring_cloud_stream_sendto_destination
I used the code below. I used functional programming.
We can get beans via ApplicationContext.
I create the channel name as a string and I get the bean according to this channelName from the application context.
MessageChannel messageChannel = createMessageChannel(channelName);
messageChannel.send(getMessageBuilder().apply(data));
public MessageChannel createMessageChannel(String channelName) {
return (MessageChannel) applicationContext.getBean(channelName);}
public Function<Object, Message<Object>> getMessageBuilder() {
return payload -> MessageBuilder
.withPayload(payload)
.setHeader(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON)
.build();}

Mocking vert.x application with PowerMockito

I'm trying to test my verticle but with mocked MongoDB (not to perform real DB actions during the process of unit testing), I've tried to mock my client, but looks like when I use vertx.deployVerticle() my mocks are not being taken into account.
Here's an example of my test setup:
#RunWith(VertxUnitRunner.class)
#PrepareForTest({ MongoClient.class })
public class VerticleTest {
#Rule
public PowerMockRule rule = new PowerMockRule();
private Vertx vertx;
private Integer port;
#Before
public void setUp(TestContext context) throws Exception {
vertx = Vertx.vertx();
mockStatic(MongoClient.class);
MongoClient mongo = Mockito.mock(MongoClientImpl.class);
when(MongoClient.createShared(any(), any())).thenReturn(mongo);
ServerSocket socket = new ServerSocket(0);
port = socket.getLocalPort();
socket.close();
DeploymentOptions options = new DeploymentOptions().setConfig(new JsonObject().put("http.port", port));
vertx.deployVerticle(TalWebVerticle.class.getName(), options, context.asyncAssertSuccess());
}
And what I actually see, that is that MongoClient.createShared is still being called, though I've mocked it.
What can I do in this case?
Edit 1.
Looks like the problem is that MongoClient is an interface and PowerMockito is not able to mock static methods in this case.
I'm still trying to find workaround for this case.
I didn't know that the MongoClient is an interface then I gave my first answer.
PowerMock doesn't supports mocking static calls interfaces (bug #510, Javaassist fixed exception, but mocking static methods still isn't supported). It will be called in next release.
I was focusing on issue in PowerMock, not why it's needed. I agree with answer which was provided in Mailing List.
You could work around it by creating a helper method in your own code
that returns MongoClient.createdShared(). Then in your test, mock that
helper to return your mocked MongoClientImp
But it will be not a work around, but right design solution. Mocking MongoClient is not a good approach, because you should not mock types you don't own.
So better way will be create a custom helper which will create MongoClientfor you and then mock this the helper in unit test. Also you will need integration tests for this helper which will call real MongoClient.createdShared().
If you don't have an opportunity to change code (or you don't want to change code without tests), then I've create an example with work around how PowerMock bug could be bypassed.
Main ideas:
create a custom MainMockTransformer. The transformer will transform interfaces classes to enable supporting mock static calls for interfaces
create a custom PowerMockRunner which will be used to add the custom MockTransformer to transformers chains.
Please, bring to notice on packages name where these new classes are located. It's important. If you want to move them into another packages then you will need to add these new packages to #PowerMockIgnore.

Static use of Dozer Mapper

Just wondering if having a static dozer mapper like this can leads to concurrency errors :
public static Mapper mapper = new DozerBeanMapper();
public static MyDTO toDTO(MyEntity e) {
MyDTO dto = mapper.map(e, MyDTO.class);
return dto;
}
Or should I always use this code :
public static MyDTO toDTO(MyEntity e) {
Mapper mapper = new DozerBeanMapper();
MyDTO dto = mapper.map(e, MyDTO.class);
return dto;
}
The method is used in an #Stateless session bean of a JBoss Server, it can be accessed concurrently. The fact is I dont really know if Dozer makes use of static variables or instance variables in the library to decide if I can/should use a static Mapper or create a new instance at every call.
Dozer instance could be static. If you would create new instance for each request the performance will be much worse, since lots of the caches will be initialised every time. ConcurrencyErrors may be encountered either due to bugs in Custom Converters or internal Dozer problems.
From the documentation, DozerMapper instance should be built as singleton. The DozerBeanMapper is thread safe so you can use at any risks with multiple threads.
To be sure you can also use DozerBeanMapperSingletonWrapper.getInstance(); This will handle the singleton part for you.
I don't thinks it is a really good idea to use the mapper as public static field.
You could also use Selma, to handle youre mapping. This is a new library based on an Annotation processor that generates the mapping code at compile time. With it youre code will look like that:
// Configure the mapping
#Mapper
public interface DtoMapper {
MyDTO toDTO(MyEntity e);
}
// Retrieve the mapper
public static DtoMapper mapper = Selma.getMapper(DtoMapper.class);
// and some where in the code use
mapper.toDto(entity);

Setting up behavior on a method appears to be calling the method

I posted this on the TypeMock forums, but am too impatient to wait for a response there. This is a very n00b question.
I'm trying to set up a fake IContainer. Here's what I have:
var container = Isolate.Fake.Instance<IContainer>();
var program = Isolate.Fake.Instance<IProgram>();
Isolate.WhenCalled(() => container.Resolve<IProgram>()).WillReturn(program);
(IProgram is an interface in my code).
When I try to run this code, I get an Autofac exception: "The requested service MyApp.IProgram has not been registered."
How could this exception be thrown though? I'm not actually calling container.Resolve(), right? I'm just setting it up to return a fake IProgram.
Unrelated background info: I'm trialing TypeMock because Autofac uses extension methods extensively and Moq won't mock them.
A couple of things that may help - first, you can mock Resolve() calls with Moq by setting up IComponentContext.Resolve(), which all of the extension methods delegate to.
Second, Autofac is designed so that you shouldn't have to use its interfaces from your components. See for examples:
http://nblumhardt.com/2010/01/the-relationship-zoo/
http://code.google.com/p/autofac/wiki/TypedNamedAndKeyedServices and
http://code.google.com/p/autofac/wiki/DelegateFactories
Where you need to use (and thus mock) IContainer or a similar interface, you can probably do the same thing using the Func, IIndex and/or Owned relationship types.
Hope this helps!
Nick
Unfortunately, there's currently a bug in Isolator, which prevents faking Autofac containers. We're working to resolve it as soon as possible.
In the mean time, is there a reason you're not using Autofac as intended, meaning have it return a fake instance, such as:
[TestFixture]
public class TestClass
{
private ContainerBuilder builder;
private IContainer container;
[SetUp]
public void SetUp()
{
builder = new ContainerBuilder();
}
[Test, Isolated]
public void Test1()
{
var fakeProgram = Isolate.Fake.Instance<IProgram>();
builder.RegisterInstance(fakeProgram).As<IProgram>();
container = builder.Build();
var program = container.Resolve<IProgram>();
Assert.AreEqual(fakeProgram, program);
}
}