public void sendMail() {
/* I have simplified the method for here */
Transport t;
t.send();
}
When I am writing unit test for this, since I don't want to actually send the mail, I want to mock the Transport class. Is it possible and if so, how to do it ?
'cglib' may fits.
Use ‘Enhancer' to proxy the 'Transport' class. In order not to actually sending the mail, you need pass into the 'Enhancer' a 'MethodInterceptor' which will not invoke the 'send()' method in super class.
Unless you really want to use mockito, you can quite easily handcraft your own test double.
What you can do is create an interface that knows how to send mail:
public interface TransportInterface {
public void send(Message msg);
}
Let the mail sending class use this interface to send the mail:
public class MailSender {
private TransportInterface transport;
public MailSender(TransportInterface transport) {
this.transport = transport;
}
public void sendMail(Message msg) {
/* This is the method from your question */
this.transport.send(msg);
}
}
In production you use an implemenation of TransportInterface that actually send the mail:
public class TransportAdapter implements TransportInterface {
private Transport transport; // Created elsewhere...
public void sendMail(Message msg) {
transport.send(msg);
}
}
And in your test code you can use a fake:
public class TransportFake implements TransportInterface {
public void sendMail(Message msg) {
// I don't send the mail!
}
}
(It's been a while since I coded java. Hope there are not too many errors. Also, you can probably do a better job naming the classes than I have.)
You can try to use Mockito library:
here is example code:
import org.mockito.Mock;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.runners.MockitoJUnitRunner;
#RunWith(MockitoJUnitRunner.class)
public class YourTestClass{
#Mock
Transport t;
#Test
public void someTest(){
t = Mockito.mock(Transport .class);
Mockito.when(t.send()).thenReturn(true);
}
}
Here is a solution which works regardless of how the Transport t object is obtained:
#Test
public sendMail(
// Mocks all current and future Transport instances,
// including those belonging to subclasses (if any).
#Capturing final Transport t)
{
new SUT().sendMail();
// Verifies that the t.send() method was called:
new Verifications() {{ t.send(); }};
}
The mocking API used above is JMockit (which I develop).
Related
Am trying to create a JUnit 5 test for a published .NET Soap Web Service using Java 1.8.
Currently, I am following a pattern from a WebServiceClient in the codebase which contains a main() method.
WebServiceClient.java:
import static com.google.common.base.Preconditions.checkNotNull;
public class WebServiceClient {
IPersonWebService service;
public WebServiceClient(IPersonWebService service) {
this.service = checkNotNull(service);
}
private PersonData getPersonData() throws Exception {
return service.getPersons(null);
}
public static void main(String [] args) {
IPersonWebService service = new IPersonWebServiceImpl().getBasicHttpBindingIPersonWebServiceImpl();
WebServiceClient client = new WebServiceClient(service);
PersonData personData = client.getPersonData();
System.out.println(personData.toString());
}
}
Need to following the same type of functionality in:
WebServiceTest.java:
import org.junit.Before;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import static com.google.common.base.Preconditions.checkNotNull;
public class WebServiceTest {
IPersonWebService service;
public WebServiceTest(IPersonWebService service) {
this.service = checkNotNull(service);
}
#Before
public void before(IPersonWebService service) {
this.service = checkNotNull(service);
}
#Test
public void testGetPersonData() throws Exception {
IPersonWebService service =
new IPersonWebServiceImpl().getBasicHttpBindingIPersonWebServiceImpl();
WebServiceTest client = new WebServiceTest(service);
PersonData personData = client.getPersonData();
assertThat(personData).isNotNull();
}
private PersonData getPersonData() throws Exception {
return service.getPersonData(null);
}
}
Running this within IntelliJ IDEA results in:
org.junit.jupiter.api.extension.ParameterResolutionException: No ParameterResolver registered for parameter [com.myapp.IPersonWebService arg0] in constructor [public com.myapp.WebServiceTest(com.myapp.IPersonWebService)].
at java.util.Optional.orElseGet(Optional.java:267)
at java.util.ArrayList.forEach(ArrayList.java:1249)
at java.util.ArrayList.forEach(ArrayList.java:1249)
IPersonWebService.java:
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebResult;
import javax.jws.WebService;
import javax.xml.bind.annotation.XmlSeeAlso;
import javax.xml.ws.RequestWrapper;
import javax.xml.ws.ResponseWrapper;
/**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.2.9-b130926.1035
* Generated source version: 2.2
*
*/
#WebService(name = "IPersonWebService", targetNamespace = "http://sample.org/")
#XmlSeeAlso({
ObjectFactory.class
})
public interface IPersonWebService {
#WebMethod(operationName = "GetPersonData",
action = "http://sample.org/IPersonWebService/GetPersonData")
#WebResult(name = "GetVehiclesResult",
targetNamespace = "http://sample.org/")
#RequestWrapper(localName = "GetPersonData",
targetNamespace = "http://sample.org/",
className = "com.myapp.GetPersonData")
#ResponseWrapper(localName = "GetPersonDataResponse",
targetNamespace = "http://sample.org/",
className = "com.myapp.GetPersonDataResponse")
public {PersonData} getPersonData(
#WebParam(name = "applicationID",
targetNamespace = "http://sample.org/")
String applicationID)
throws IPersonWebServicetExceptionFaultMessage;
}
This contains the actual WSDL that will be imported into memory.
IPersonWebServiceImpl.java:
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebEndpoint;
import javax.xml.ws.WebServiceClient;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
/**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.2.9-b130926.1035
* Generated source version: 2.2
*
*/
#WebServiceClient(name = "IPersonWebServiceImpl",
targetNamespace = "http://sample.org/",
wsdlLocation = "https://sample.com/WCF/IPersonWebServiceImpl.svc?singleWsdl")
public class IPersonWebServiceImpl
extends Service
{
private final static URL IPersonWebServiceImpl_WSDL_LOCATION;
private final static WebServiceException IPersonWebServiceImpl_EXCEPTION;
private final static QName IPersonWebServiceImpl_QNAME = new QName("http://sample.org/", "IPersonWebServiceImpl");
static {
URL url = null;
WebServiceException e = null;
try {
url = new URL("https://sample.com/WCF/IPersonWebServiceImpl.svc?singleWsdl");
} catch (MalformedURLException ex) {
e = new WebServiceException(ex);
}
IPersonWebServiceImpl_WSDL_LOCATION = url;
IPersonWebServiceImpl_EXCEPTION = e;
}
public IPersonWebServiceImpl() {
super(__getWsdlLocation(), IPersonWebServiceImpl_QNAME);
}
public IPersonWebServiceImpl(final WebServiceFeature... features) {
super(__getWsdlLocation(), IPersonWebServiceImpl_QNAME, features);
}
public IPersonWebServiceImpl(final URL wsdlLocation) {
super(wsdlLocation, IPersonWebServiceImpl_QNAME);
}
public IPersonWebServiceImpl(final URL wsdlLocation,
final WebServiceFeature... features) {
super(wsdlLocation, IPersonWebServiceImpl_QNAME, features);
}
public IPersonWebServiceImpl(final URL wsdlLocation,
final QName serviceName) {
super(wsdlLocation, serviceName);
}
public IPersonWebServiceImpl(final URL wsdlLocation,
final QName serviceName,
final WebServiceFeature... features) {
super(wsdlLocation, serviceName, features);
}
#WebEndpoint(name = "BasicHttpBinding_IPersonWebServiceImpl")
public IPersonWebServiceImpl getBasicHttpBindingIPersonWebServiceImpl() {
return super.getPort(new QName("http://sample.org/",
"BasicHttpBinding_IPersonWebServiceImpl"),
IPersonWebServiceImpl.class);
}
#WebEndpoint(name = "BasicHttpBinding_IPersonWebServiceImpl")
public IPersonWebServiceImpl getBasicHttpBindingIPersonWebServiceImpl(final WebServiceFeature... features) {
return super.getPort(new QName("http://sample.org/",
"BasicHttpBinding_IPersonWebServiceImpl"),
IPersonWebServiceImpl.class, features);
}
private static URL __getWsdlLocation() {
if (IPersonWebServiceImpl_EXCEPTION!= null) {
throw IPersonWebServiceImpl_EXCEPTION;
}
return IPersonWebServiceImpl_WSDL_LOCATION;
}
}
Question(s):
When trying to follow along using the pattern inside WebServiceClient.java, why does WebServiceTest.java fail with this:
org.junit.jupiter.api.extension.ParameterResolutionException:
No ParameterResolver registered for parameter...
How to resolve this?
The WebServiceClient.java works and shows PersonData which was obtained from the IPersonWebServiceImpl.java (notice how this has the WSDL explicitly setup inside the static clause).
Is there a 3rd party open source Java framework which I can use to import any type of WSDL (.NET or others) and test SOAP based endpoints using JUnit 5?
Come from a RESTful Web Services background and not a SOAP based background, so any suggestions would be most appreciated.
So firstly, thanks for providing loads of code and making your question clear. I see it's been a few months since you asked, but I'll try and help.
I think there's two problems: the exception (tldr it's a junit version clash), and structuring code for writing unit tests.
ParameterResolutionException
#Test is imported from JUnit5, aka 'junit-jupiter', but #Before is from JUnit4, aka 'junit-vintage' or 'junit'.
import org.junit.Before; // junit4
import org.junit.jupiter.api.BeforeAll; // junit5
import org.junit.jupiter.api.Test; // junit5
Because the #Test is from junit-jupiter, the tests are run with JUnit5, which (unlike JUnit4) allows for parameters in test and constructors methods. WebServiceTest's constructor needs a parameter. But you don't have a provider for IPersonWebService, so JUnit5 breaks - it can't resolve it.
So to fix this:
remove the constructor
remove the parameter from the before method
change #Before to #BeforeEach (and fix the imports)
I'd also recommend (if possible) that you exclude any JUnit4 dependencies that you might have added (junit-vintage is for backwards compatibility), or might have been snuck in from other dependencies. It prevents confusions like this.
For example with maven, to see which JUnit versions there are, and their origins, view and filter the dependency tree:
mvn dependency:tree -Dincludes="*junit*"
Writing unit tests
I'm not sure what the application is intended to be, but (as I think you've found out) it's difficult to test. It certainly looks strange to me. WebServiceClient has a main method (I guess it gets called directly?) that immediately creates the API and calls it and returns the result - so there's no separation between the 'business logic' and 'api'. Maybe that main method is there for demonstrating?
It would be best to split things up. Hopefully then it makes testing more clear.
Let's make a dedicated WebServiceClient. This should be the only class that interacts with IPersonWebService.
There shouldn't be any sort of fancy logic in here, just simple API calls with basic exception handling.
// import generated soap stuff
public class WebServiceClient {
private final IPersonWebService service;
public WebServiceClient(IPersonWebService service) {
// an instance of the API is received in the constructor
this.service = service;
}
private PersonsData getPersonData() throws WebServiceClientException {
try {
// call the API
PersonsData persons = service.getPersonData(null);
if (personsData == null) {
throw new WebServiceClientException("Received null response from PersonsData :(");
}
return persons;
} catch (IPersonWebServicetExceptionFaultMessage e) {
// wrap the SOAP exception in our own wrapper
// it's best not to let SOAP code spread into our project.
throw new WebServiceClientException("Tried fetching PersonsData, but got exception from API", e);
}
}
}
And here's the test class for that service.
Each #Test method is completely independent from the others, it has its own little bubble to keep the tests independent.
I really recommend using a mocking framework, like Mockito, to create dummy instances. It's really powerful. In this case it means we can easily test exceptions. Mockito 3 works really well with JUnit5 - I've used the parameter injection here to make mocks for the tests (Mockito provides a Parameter Resolver under the hood).
#ExtendWith(MockitoExtension.class)
class WebServiceClientTest {
#Test
public void testWebServiceClientCreated(
// it's not actually important about the internal workings of IPersonWebService
// so use mockito to mock it!
// all we care about is that if it's there, then WebServiceClient can be created
#Mock
IPersonWebService service) {
WebServiceClient wsc = new WebServiceClient(service);
assertNotNull(wsc);
}
// test happy flow
#Test
public void testPersonsDataReturned(
// again, we don't care about the internals of IPersonWebService, just that it returns data
// so mock it!
#Mock
IPersonWebService service,
// it's also not important about the internals of PersonsData,
// just that it's an object that's returned
#Mock
PersonsData personsDataMock) {
// set up the mock
when(service.getPersonsData(isNull())).thenReturn(personsDataMock);
WebServiceClient wsc = new WebServiceClient(service);
// we don't need to check WebServiceClient here! We already have a test that does this.
// each test should only focus on one thing
// assertNotNull(wsc);
PersonsData result = wsc.getPersonsData();
// now we can check the result
assertNotNull(result);
assertEquals(personsDataMock, result);
}
// again, testing for failure is much more interesting than happy flows
// in this case, the test will fail!
// we'd better fix WebServiceClient to handle unexpected exceptions from IPersonWebService
#Test
public void testWhenApiThrowsNullPointerExceptionExpectWebServiceClientException(
#Mock
IPersonWebService service) {
// mock throwing an exception
NullPointerException npe = new NullPointerException("Another one of those weird external webservice exceptions");
doThrow()
.when(service.getPersonsData(isNull()));
WebServiceClient wsc = new WebServiceClient(service);
WebServiceClientException thrownException = assertThrows(WebServiceClientException.class,
() -> wsc.getPersonsData()
);
// now we can check the result
assertNotNull(thrownException);
assertEquals("Tried fetching PersonsData, but got exception from API", thrownException.getMessage());
assertEquals(npe, thrownException.getCause());
}
}
And a nice wrapper for any exceptions when dealing with the API.
class WebServiceClientException extends Exception {
public WebServiceClientException(String message) {
super(message);
}
public WebServiceClientException(String message, Exception cause) {
super(message, cause);
}
}
I have a class:
public class RequestHandler implements HttpHandler {
public void handleRequest(HttpServerExchange serverContext) throws Exception {
serverContext.dispatch(() -> serverContext.getRequestReceiver()
.receiveFullBytes((httpServerExchange, reqBytes) -> {
// business logic along with few function call
}
)
);
}
}
I want to write a unit test case to test my business logic. I am not sure how to do it with 2 levels of a lambda expression insider a dispatcher? Can someone please suggest a good way to write test cases?
I know that we can move business logic to new class and can test it (i guess it's better designed) but curious to know what if it's part of some legacy code or something that we can't change, how can we test it?
Under the assumption that somewhere in your buisness logic you forward the received message (or whatever you do with it) to somewhere else, you can just test your code as usual.
Note that HttpServerExchange is a final class, so you need to use a Mockito version that supports final mocking - and you have to enable it, as described here.
To get around the lambda expression you need to use thenAnswer or doAnswer to trigger the invocation of the correct interface method manually.
A simple example could look like this:
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.ArgumentCaptor;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.jupiter.MockitoExtension;
import org.mockito.stubbing.Answer;
import io.undertow.io.Receiver;
import io.undertow.io.Receiver.FullBytesCallback;
import io.undertow.server.HttpHandler;
import io.undertow.server.HttpServerExchange;
#ExtendWith(MockitoExtension.class)
public class RequestHandlerTest {
static class BuisnessLogic {
public void someMethod(HttpServerExchange httpServerExchange, byte[] reqBytes) {
}
}
static class RequestHandler implements HttpHandler {
BuisnessLogic logic;
public void handleRequest(HttpServerExchange serverContext) throws Exception {
serverContext.dispatch(
() -> serverContext.getRequestReceiver().receiveFullBytes(
(httpServerExchange, reqBytes) -> {
logic.someMethod(httpServerExchange, reqBytes);
}
)
);
}
}
#Mock
BuisnessLogic logic;
#InjectMocks
RequestHandler handler;
#Test
public void test() throws Exception {
byte[] message = new byte[] {1,2,3};
HttpServerExchange serverContext = Mockito.mock(HttpServerExchange.class);
// 1st lambda
Mockito.when(serverContext.dispatch(Mockito.any(Runnable.class)))
.thenAnswer((Answer<HttpServerExchange>) invocation -> {
Runnable runnable = invocation.getArgument(0);
runnable.run();
return serverContext;
});
// 2nd lambda
Receiver receiver = Mockito.mock(Receiver.class);
Mockito.doAnswer((Answer<Void>) invocation -> {
FullBytesCallback callback = invocation.getArgument(0);
callback.handle(serverContext, message);
return null;
}).when(receiver).receiveFullBytes(Mockito.any(FullBytesCallback.class));
Mockito.when(serverContext.getRequestReceiver()).thenReturn(receiver);
// class under test - method invocation
handler.handleRequest(serverContext);
// buisness logic call verification
ArgumentCaptor<HttpServerExchange> captor1 = ArgumentCaptor.forClass(HttpServerExchange.class);
ArgumentCaptor<byte[]> captor2 = ArgumentCaptor.forClass(byte[].class);
Mockito.verify(logic).someMethod(captor1.capture(), captor2.capture());
Assertions.assertEquals(serverContext, captor1.getValue());
Assertions.assertEquals(message, captor2.getValue());
}
}
As others already mentioned you should only use that approach for legacy code.
A simple refactoring could just push the entire part you need to test into its own method, which - in the example above - would just be the buisness logic itself.
There is no explicit need to test the undertow framework yourself.
I have this below method.
protected static String encode(String url) {
try {
url = URLEncoder.encode(url, StandardCharsets.UTF_8.toString());
} catch (Exception e) {
LOGGER.warn("exception occured while encoding url {}", url);
}
return url;
}
I am unable to provide a junit test for this because I can't mock URLEncoder. There are 2 possible outcomes of this method
encoded url
original url if there is some exceptions
I am able to create a test method for first outcome. how would you create test method for the second outcome?
The fundamental theorem of software engineering (FTSE) is a term originated by Andrew Koenig to describe a remark by Butler Lampson attributed to the late David J. Wheeler:
"We can solve any problem by introducing an extra level of indirection."
[...]
The theorem is often expanded by the humorous clause "…except for the problem of too many levels of indirection," referring to the fact that too many abstractions may create intrinsic complexity issues of their own. (Source: Wikipedia)
So let's say there's a class that has a static method named encode:
public final class UrlHelper {
protected static String encode(String url) {
try {
url = URLEncoder.encode(url, StandardCharsets.UTF_8.toString());
} catch (Exception e) {
LOGGER.warn("exception occured while encoding url {}", url);
}
return url;
}
}
and your code depends on it:
public class MyClass {
public void doSomething(String someUrl) {
// ...
String encodedUrl = UrlHelper.encode(someUrl);
// ...
}
}
and you want to test MyClass.doSomething(String someUrl) but you want to mock UrlHelper.encode(someUrl). One option is to define another class such as
public final class MyUrlHelper {
protected String encode(String url) {
return UrlHelper.encode(someUrl);
}
}
As MyUrlHelper.encode(String url) is not static, you can refactor your original code and test it by relying on dependency injection and mocking the non-static MyUrlHelper.encode(String url):
// Refactored
public class MyClass {
private MyUrlHelper myUrlHelper;
public UrlHelper(MyUrlHelper muUrlHelper) {
this.myUrlHelper = myUrlHelper;
}
public void doSomething(String someUrl) {
// ...
String encodedUrl = myUrlHelper.encode(someUrl);
// ...
}
}
// Test
#Test
public void myTest() {
// setup myUrlHelper and configure it
MyUrlHelper myUrlHelper = mock(MyUrlHelper.class);
when(myUrlHelper.encode(...)).thenReturn(...);
// inject
MyClass myObject = new MyClass(myUrlHelper);
// stimulate
myObject.doSomething("...")
}
Another option is to use Mockito using the PowerMockRunner as explained by #Marimuthu Madasamy.
However, I don't see any benefit in mocking UrlHelper.encode or URLEncoder.encode here. It is not an external system (a database, a file system, a message broker, a SOAP API, a REST API, etc.) so I don't see any gains by mocking it.
You could use PowerMockito to mock static methods. Assuming the static method in your post is in a class called HelloWorld, here are the two tests where the first test is testing the positive case and the second test
is testing the exception case:
import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.powermock.api.mockito.PowerMockito.doThrow;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
#RunWith(PowerMockRunner.class)
#PrepareForTest(HelloWorld.class)
public class HelloWorldTest {
#Test
public void encode_returnsEncoded() throws UnsupportedEncodingException {
// given
mockStatic(URLEncoder.class);
when(URLEncoder.encode(any(String.class), any(String.class)))
.thenReturn("testUrlEncoded");
// when
String encoded = HelloWorld.encode("testUrl");
// then
assertThat(encoded).isEqualTo("testUrlEncoded");
}
#Test
public void encode_returnsInputOnException() {
// given
mockStatic(URLEncoder.class);
doThrow(new Exception("exception from test"))
.when(URLEncoder.class);
// when
String encoded = HelloWorld.encode("testUrl");
// then
assertThat(encoded).isEqualTo("testUrl");
}
}
If you are willing to use Lombok, I got a practical approach for you:
#lombok.Generated // Function won't raise up in Jacoco coverage report, see https://stackoverflow.com/a/56327700/1645517
#lombok.SneakyThrows(UnsupportedEncodingException.class) // Suppress handling this exception, see https://projectlombok.org/features/SneakyThrows
private static String urlEncode(final String valueToEncode) {
return URLEncoder.encode(valueToEncode, StandardCharsets.UTF_8.name());
}
Jacoco will ignore this method
The UnsupportedEncodingException cannot be thrown here. Let Lombok handle this ugly circumstance.
I have the following application class which uses a server to run its logic
Implementation of the application class is as follows:
package edu.umd.fcmd.guice.application;
import com.google.inject.Guice;
import com.google.inject.Injector;
public class WebApplication {
private WebServer server;
public void run() {
System.out.println("starting web application...");
Injector injector = Guice.createInjector(new WebGuiceModule());
server = injector.getInstance(WebServer.class);
server.run();
System.out.println("web application finished.");
}
public static void main(String[] args) {
WebApplication app = new WebApplication();
app.run();
}
}
The server class is as follows which depends on three interfaces:
public class WebServer{
private final Frontend frontend;
private final Middleware middleware;
private final Persistance persistance;
#Inject
public WebServer(#Named("front")Frontend frontend, #Named("middle")Middleware middleware, #Named("pers")Persistance persistance) {
this.frontend = frontend;
this.middleware = middleware;
this.persistance = persistance;
}
public String getType() {
return "WebServer";
}
public boolean run() {
System.out.println("running " + this.getType());
Injector injector = Guice.createInjector();
Frontend frontend = injector.getInstance(Frontend.class);
frontend.run();
Middleware middleware = injector.getInstance(Middleware.class);
middleware.run();
Persistance persistance = injector.getInstance(Persistance.class);
persistance.run();
return true;
}
}
My webguicemodule is as follows:
public class WebGuiceModule extends AbstractModule{
#Override
protected void configure(){
bind(WebServer.class).annotatedWith(Names.named("front")).to(FrontEnd.class);
bind(WebServer.class).annotatedWith(Names.named("middle")).to(Middleware.class);
bind(WebServer.class).annotatedWith(Names.named("pers")).to(Persistance.class);
}
}
I am not sure why my module is not working properly. It is still in errors when I am writing the bind statements. Could not figure out why
I am receiving the following errors:
Exception in thread "main" java.lang.Error: Unresolved compilation problems:
The method to(Class<? extends WebServer>) in the type LinkedBindingBuilder<WebServer> is not applicable for the arguments (Class<FrontEnd>)
FrontEnd cannot be resolved to a type
The method to(Class<? extends WebServer>) in the type LinkedBindingBuilder<WebServer> is not applicable for the arguments (Class<Middleware>)
Middleware cannot be resolved to a type
The method to(Class<? extends WebServer>) in the type LinkedBindingBuilder<WebServer> is not applicable for the arguments (Class<Persistance>)
Persistance cannot be resolved to a type
You are not using bind() correctly. You've configured WebGuiceModule such that FrontEnd, Middleware, and Persistance are subclasses of WebServer. However, the compiler errors indicate that is not the case.
You just need to say:
bind(FrontEnd.class);
bind(Middleware.class);
bind(Persistance.class);
Then when you ask the injector for an instance of WebServer, it will know how to create the objects that it needs to pass into the constructor.
WebServer server = injector.getInstance(WebServer.class);
In this case, you don't need #Named. That is for a case like this:
public class Foo {
#Inject
public Foo(#Named("bar") Jar bar, #Named("tar") Jar tar) {
}
}
public interface Jar {}
public class Bar extends Jar {}
public class Tar extends Jar {}
Then in a module...
bind(Jar.class).annotatedWith(Names.named("bar")).to(Bar.class);
bind(Jar.class).annotatedWith(Names.named("tar")).to(Tar.class);
The "name" disambiguates which implementation of Jar to create and inject. Otherwise it wouldn't know, and it would error.
Thank you #JeremyHeiler. This Frontend interface happens to be in a different package. Now, Frontend is dependent on an interface called authentication. When I tried implementing it with the similar code as that of the webserver, I am getting errors. The code I wrote was the following:
package edu.umd.fcmd.guice.interfaces;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import edu.umd.fcmd.guice.application.WebServer;
import edu.umd.fcmd.guice.interfaces.Authentication;
public interface Frontend{
private final Authentication authentication;
#Inject
public interface(Authentication authentication) {
System.out.println("5");
this.authentication = authentication;
}
public static String getType(){
return "Frontend";
}
public default boolean run(){
System.out.println("in frontend");
authentication.run();
return true;
}
}
Errors are the following:
Multiple markers at this line
- Duplicate field Frontend.authentication
- Illegal modifier for the interface field Frontend.authentication; only public, static & final are
permitted
Syntax error on token "interface", Identifier expected
The static field Frontend.authentication should be accessed in a static way
I have tried searching a lot on the internet but could not find figure out. I guess the problem is having files in different packages. If you could please let me know.
I have an integrator class which I need to test, the class constructor instantiates a service client. As the service client is an external dependency, I want to test the individual responsibility of the integrator. The code looks like this.
public class Integrator {
Client client;
public Integrator() {
client = new RemoteClient();
}
public String invokeClient() {
....
}
}
What can be the best way to mock this ? Also, I need to make sure of the code coverage.
Use Dependency Injection so you don't create the Client:
public Integrator(Client client) {
//... argument checking omitted
this.client = client;
}
Now your tests can create mock Clients which can be passed in directly.
You can still keep the no-arg constructor as well:
public Integrator() {
this(new RemoteClient());
}