Here is my first class where the constructor has an object calling methods in other class.
Class Search{
public Search(String username, JSONObject accounts) throws Exception {
Credentials credentials = new Credentials(username);
String Uid = credentials.getUserName();
String Pwd = new String(credentials.getCredentials().getPassword());
}
public getDOB(){
--------------------
-------------
}
}
Class Credentaials:
import javax.resource.spi.security.PasswordCredential;
Public class Credentials{
public Credentials(String name){
}
public PasswordCredential getCredentials(){
return passwordCredential;
}
public String getUserName(){
PasswordCredential localCredential = getCredentials();
return localCredential.getUsername();
}
}
Class test:
#RunWith(PowerMockRunner.class)
#PrepareForTest({Search.class, Credentials.class})
public class JunitTest {
#Test
public void playTest() {
PasswordCredential pwdCreds = new PasswordCredential();
pwdCreds.setPassword("test");
Credentials credentials = new Credentials("user");
Credentials credentials = Mockito.spy(credentials);
Mockito.doReturn(pwdCreds).when(credentials).getCredentials();
Mockito.doReturn("cmApptest").when(credentials).getUserName();
Search search = new Search("username", jsonobject);
search.getDOB();
}
}
Whenever I debug the test class, it is executing the getCredentials and getUserName methods even after I mocked them. I was expecting the actual methods not to execute, instead it should return the values as I mentioned in the JunitTest class.
You aren't replacing the real version of Credentials that is being used in your Search class with a mock. Rather, you're clearly creating and using a real Credentials object inside of your Search object's constructor. For mocking to work, you have to actually replace the credentials object in your Search object with a mock. Just creating a mock of the same type somewhere in your code doesn't cause it to replace instances of the real object somewhere else in your code.
Often, dependency injection is used to introduce mocking, like with Spring. Here's a simple way to do what you want. Redefine your Search constructor like this:
class Search {
Search(String username, JSONObject accounts, Credentials creds) throws Exception {
Credentials credentials = creds? creds : new Credentials(username);
String Uid = credentials.getUserName();
String Pwd = new String(credentials.getCredentials().getPassword());
}
Search(String username, JSONObject accounts) throws Exception {
this(username, accounts, null);
}
}
The behavior of your production code will not be affected, but you can optionally construct Search with a mock.
Credentials credentials = new Credentials("user");
Credentials credentials1 = Mockito.spy(credentials);
Mockito.doReturn(pwdCreds).when(credentials1).getCredentials();
Mockito.doReturn("cmApptest").when(credentials1).getUserName();
Search search = new Search("username", jsonobject, credentials1);
search.getDOB();
There's no magic in terms of your code using a mock rather than the real object. Mocking frameworks just let you easily create stand-in objects that act in very specific ways for testing. You still have to cause those objects to be used by your code.
Also, you don't really need/want a spy here. You really want a mock, because you're defining the behavior of all of the methods in Credentials. With a mock, you wouldn't need to instantiate your Credentials object at all. So the first lines of the test code I gave above could could be:
Credentials credentials1 = Mockito.mock(Credentials.class);
(or something like this. I'm not actually trying this code)
Related
Suppose, there's a site that provides an API, such as this:
Users post questions, answers on that site
You can make GET and
POST calls
There are two types of authentication: weak (only gives
read rights) and strong (gives both read and write rights)
Right now, I'd like to read users' questions and answers (only need weak access) and send them messages or post my own questions in the future (would need strong access)
The site's API has actions both to do with users (e.g. send a message) and with site in general (see about, see most popular questions)
What I have right now looks like this:
public class Wrapper {
private AccessToken accessToken;
public Wrapper(...) {
//does some stuff
//gets access token:
getAccessToken(...);
}
public AccessToken getAccessToken(...) {
AccessToken result;
//gets access token, given the auth info provided as arguments
accessToken = result;
return result;
}
public ArrayList<Question> getQuestions(User user) {
//gets user's questions, using the accessToken field
//set's a user's questions field to the result and returns the result
}
public ArrayList<Answer> getAnswers(User user) {
//same as previous
}
public boolean sendMessage(User user) {
//sends a message, if current accessToken is strong
}
}
and User class:
class User {
private String username;
private ArrayList<Question> questions;
private ArrayList<Answer> answers;
public User(String username) {this.username=username;}
//getters and setters
}
So, to use it you would use something like this:
public class Main {
public static void main(String[] args) {
Wrapper wrapper = new Wrapper(...);
ArrayList<Question> questions = wrapper.getQuestions(new User("username"));
wrapper.sendMessage(new User("username2"));
}
}
I have issues with this.
First of all, class User feels superfluous, since all the functionality is inside the Wrapper class.
Second, I wonder if what my methods do is wright - from the design's perspective: in getAccessToken I both return AccessToken and set a Wrapper's field accessToken to the result. Is this the right approach? Or should the method only return access token and then that result should be assigned to a class' field explicitly? Same goes for the getQuestions and getAnswers methods: they both get the ArrayLists, return them and assign a User's field to the result - all inside the single method.
I would like for a User class to have some meaning. I thought of doing it something like that:
Wrapper wrapper = new Wrapper(...);
User user = new User("username");
user.getQuestions(wrapper.getAccessToken());
user.sendMessage(wrapper.getAccessToken());
So, the Wrapper class would only serve as a place to get an access token from, which doesn't feel right as well. I could place the access token functionality inside the User class and use it like this:
User user = new User("username", ...);
user.getQuestions();
user.sendMessage();
The User's constructor would take both username and auth data, would get access token and store it inside a user and then use it when getting questions/answers or sending messages. I could make the accessToken field inside User class static so that all users shared the same token.
However, there are actions the site API provides, that aren't obviously connected with users: for instance, getting the site's most popular questions. It feels right to use a generic Wrapper class for that purpose which contradicts with the previous approach.
I'm new to this and only know a couple design patterns. Perhaps, there are widespread patterns that are to be used for this type of problem? Any help/advice is appreciated.
There are a few alternatives that you can do to solve your problem, but there is likely not one that is better than all others. The solution you choose will depend on the trade-offs and how you want your system to operate. The following are two common solutions to this type of problem.
Have the Wrapper generate a User: Instead of generating a User object separate from the Wrapper, you can have the Wrapper generate the User object. This allows the Wrapper to embed the AccessToken within the User without any outside client knowing that a user has an AccessToken. For example, you can use the following Wrapper and User definitions:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
}
class User {
private String username;
private final AccessToken token;
public User(String username, AccessToken token) {
this.user = user;
this.token = token;
}
// ... getters and setters ...
}
Note that getAccessToken is now private, as no other client needs to access this method. All of the methods of Wrapper continue to accept a User argument, but they now should obtain the access token by calling getToken on the User object, rather than using a stored AccessToken in Wrapper.
Also note that the token field is final, since the access token associated with a User should not change over the life of a User object.
Embed the Wrapper in User: This technique is similar to (1), but it also embeds the Wrapper object in the User object. This allows the User class to act as a live object, which can be queried for questions and answers and can be used to send messages. Since all of the methods of Wrapper accept a User argument, this is a good sign that the methods should be moved to User. The following is a halfway point to refactor the Wrapper methods into User:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
public ArrayList<Question> getQuestions(User user) {
//gets user's questions, using the accessToken field
//set's a user's questions field to the result and returns the result
}
public ArrayList<Answer> getAnswers(User user) {
//same as previous
}
public boolean sendMessage(User user) {
//sends a message, if current accessToken is strong
}
}
class User {
private String username;
private final AccessToken token;
private final Wrapper wrapper;
public User(String username, AccessToken token, Wrapper wrapper) {
this.user = user;
this.token = token;
this.wrapper = wrapper;
}
public List<Question> findQuestions() {
return wrapper.getQuestions(this);
}
public ArrayList<Answer> findAnswers() {
return wrapper.getAnswers(this);
}
public boolean sendMessage() {
return wrapper.sendMessage(this);
}
// ... getters and setters ...
}
Using this technique, clients can now directly get questions and answers from a User object. Note that the findQuestions and findAnswers methods start with find. This tips off clients that this call may be a long call (as opposed to getQuestions or getAnswers, which would make a client assume that it is a simple getter and the method would return nearly-instantly). The fact that these methods execute a remote call should also be documented in the Java-docs for the methods. If the call takes a long time, the methods should return a Future (or a similar object) and be made asynchronously.
If you want to go all-in on the refactor, you can move all of the implementation details from the Wrapper class to the User class:
public class Wrapper {
public Wrapper(...) {
// ... does some stuff, but DOES NOT get an access token ...
}
private AccessToken getAccessToken(...) {
AccessToken result;
// ... gets access token, given the auth info provided as arguments ...
return result;
}
public User findUser(String username, ...) {
return new User(username, getAccessToken(...));
}
}
class User {
private String username;
private final AccessToken token;
private final Wrapper wrapper;
public User(String username, AccessToken token, Wrapper wrapper) {
this.user = user;
this.token = token;
this.wrapper = wrapper;
}
public List<Question> findQuestions() {
// ... find the questions remotely ...
}
public ArrayList<Answer> findAnswers() {
// ... find the answers remotely ...
}
public boolean sendMessage() {
// ... send message remotely ...
}
// ... getters and setters ...
}
This may not be the best approach, as it may be a better idea to keep the details of accessing the remote API abstracted in the Wrapper class. This is a judgment call that will depend on the nature of your specific application.
There are numerous other techniques that you can do, but the above two are common approaches to the problem you are trying to solve.
I need to unit test a method, and I would like mock the behavior so that I can test the necessary part of the code in the method.
For this I would like access the object returned by a private method inside the method I am trying to test. I created a sample code to give a basic idea of what I am trying to achieve.
Main.class
Class Main {
public String getUserName(String userId) {
User user = null;
user = getUser(userId);
if(user.getName().equals("Stack")) {
throw new CustomException("StackOverflow");
}
return user.getName();
}
private User getUser(String userId) {
// find the user details in database
String name = ""; // Get from db
String address = ""; // Get from db
return new User(name, address);
}
}
Test Class
#Test (expected = CustomException.class)
public void getUserName_UserId_ThrowsException() {
Main main = new Main();
// I need to access the user object returned by getUser(userId)
// and spy it, so that when user.getName() is called it returns Stack
main.getUserName("124");
}
There are only two ways to access private:
using reflection
extend the scope
maybe waiting for Java 9 to use new scope mechanisms?
I would change the scope modifier from private to package scope. Using reflection is not stable for refactoring. It doesn't matter if you use helpers like PowerMock. They only reduce the boiler-plate code around reflection.
But the most important point is you should NOT test too deep in whitbox tests. This can make the test setup explode. Try to slice your code into smaller pieces.
The only information the method "getUserName" needs from the User-object is the name. It will validate the name and either throw an exception or return it. So it should not be necessary to introduce a User-object in the test.
So my suggestion is you should extract the code retreiving the name from the User-object into a separate method and make this method package scope. Now there is no need to mock a User-Object just the Main-Object. But the method has its minimal information available to work properly.
class Main {
public String getUserName(String userId) {
String username = getUserNameFromInternal(userId);
if (userName.equals("Stack")) {
throw new CustomException("StackOverflow");
}
return user.getName();
}
String getUserNameFromInternal(String userId) {
User user = getUser(userId);
return user.getName();
}
...
}
The test:
#Test (expected = CustomException.class)
public void getUserName_UserId_ThrowsException() {
Main main = Mockito.mock(new Main());
Mockito.when(main.getUserNameInternal("124")).thenReturn("Stack");
main.getUserName("124");
}
Your problem that call to new within your private method.
And the answer is not to turn to PowerMock; or to change the visibility of that method.
The reasonable answer is to "extract" that dependency on "something that gives me a User object" into its own class; and provide an instance of that class to your "Main" class. Because then you are able to simply mock that "factory" object; and have it do whatever you want it to do.
Meaning: your current code is simply hard-to-test. Instead of working around the problems that are caused by this, you invest time in learning how to write easy-to-test code; for example by watching these videos as a starting point.
Given your latest comment: when you are dealing with legacy code, then you are really looking towards using PowerMockito. The key part to understand: you don't "mock" that private method; you rather look into mocking the call to new User() instead; as outlined here.
You can use a PowerMock's mockPrivate but I don't recommend it.
If you has such a problem it usually mean that your design is bad.
Why not making the method protected?
I'm trying to implement a database authentication with Eclipse Scout.
For that I created a class DataSourceCredentialVerifier in the client module, which implements the ICredentialVerifierinterface. Then I adapted the init method of the UiServletFilter class to use my verifier.
public class DataSourceCredentialVerifier implements ICredentialVerifier {
private static final Logger LOG = LoggerFactory.getLogger(DataSourceCredentialVerifier.class);
#Override
public int verify(String username, char[] password) throws IOException {
Object queryResult[][] = BEANS.get(IMySqlAuthService.class).load();
return AUTH_OK;
}
I haven't implemented any authentication logic yet. My task now is to establish a clean database connection.
For that I created the following interface in the shared module:
public interface IMySqlAuthService extends IService {
Object[][] load();
}
The implementation is in the server module:
public class MySqlAuthService implements IMySqlAuthService {
#Override
public Object[][] load() {
String sql = "select username, password from users ";
Object[][] queryResult = SQL.select(sql, null, null);
return queryResult;
}
}
First I want to see, if there is at least something in the query, but I get an AssertionException here:
Object queryResult[][] = BEANS.get(IMySqlAuthService.class).load();
org.eclipse.scout.rt.platform.util.Assertions$AssertionException: Assertion error: no instance found for query: interface org.eclipse.scout.app.shared.services.IMySqlAuthService
at org.eclipse.scout.rt.platform.util.Assertions.fail(Assertions.java:580)
at org.eclipse.scout.rt.platform.util.Assertions.assertNotNull(Assertions.java:87)
at org.eclipse.scout.rt.platform.BEANS.get(BEANS.java:41)
I don't get an instance of my MySqlAuthService implementation. I assume that the BeanManager should have created an instance for me. MySqlAuthService should be registered as a Bean, since my IMySqlAuthService interface extends from IService which has the #ApplicationScoped annotation.
Adding the #Bean annotation to MySqlAuthService results in the same exception.
Here some information about the BeanManager and annotations:
https://eclipsescout.github.io/6.0/technical-guide.html#sec-bean.manager
Here is another different approach s.o. tried, but it doesn't feel correct:
https://www.eclipse.org/forums/index.php/t/1079741/
How can I get my example to work with my service?
Here is the working solution with important explanations of Eclipse Scout principles.
The source is summarized information of the Eclipse-Scout-Technical-Guide.
In Scout there is a built in annotation: #TunnelToServer. Interfaces marked with this annotation are called on the server. The server itself ignores this annotation.
To achieve that a bean is registered on client side, this annotation is required. The platform cannot (!) directly create an instance for these beans, a specific producer is registered which creates a proxy that delegates the call to the server.
My first clear mistake was that I hadn't annotated the IMySqlAuthServicewith #TunnelToServer.
After this addition I got rid of the no instance AssertionError.
After that my code ran into the HTTP status-code: 403 access forbidden.
This occured because my code didn't run in the correct Thread. That is the current RunContext. I had to use this lines of code in my verify method of the DataSourceCredentialVerifier:
Subject subject = new Subject();
subject.getPrincipals().add(new SimplePrincipal("system"));
subject.setReadOnly();
RunContext runContext = RunContexts.copyCurrent().withSubject(subject);
Now one can use the runContext's call() or run() method, depending whether the code returns a result. The action is run in the current thread, meaning that the caller is blocked until completion.
Concrete example solution:
Object[][] result = runContext.call(new Callable<Object[][]>() {
#Override
public Object[][] call() throws Exception {
return BEANS.get(IMySqlAuthService.class).load();
}
});
//TODO implement authentication logic.
For more information about the RunContext see here:
https://eclipsescout.github.io/6.0/technical-guide.html#runcontext
How to mock the object for the Phone object.
code bellow,
public class Fortest {
UserDao userdao = new UserDao();
Phone name = new Phone();
public String handleUser(User user) {
String returncode="failed";
//User usr = new User("bob");
String username=user.getUsername();
String pass=user.getPass();
System.out.println("username and password : "+username+" : "+pass);
Phone name = new Phone();
String ph = name.getA();
System.out.println("ph "+ph);
if(ph.equalsIgnoreCase("test")){
System.out.println("A "+ph);
returncode="done";
}
System.out.println("returning "+returncode);
return returncode;
//System.out.println("name "+name.toString());
//System.out.println(name.getA());
}
}
Thanks
First I'm going to make some assumptions.
user.getUsername() & user.getPass() have no side affects.
The System.out.println are not important to you.
Thus done your class becomes:
public class Fortest {
Phone name = new Phone();
public String handleUser(User user) {
String ph = name.getA();
if(ph.equalsIgnoreCase("test")){
return "done";
}
return "failed";
}
}
So your test has two conditions. Either phone.getA() is "test" and you return "done" or it is not and you return "failed".
So how to set set "getA". One thing is for sure, we will need to be able set "name" from the test. For that we need to "inject" it (we can do it a number of other ways, but I loves injection). I'd use Guice, many would use Spring. Some would use one of the other injection frameworks. But in the tests most of us would use manual injection.
public class Fortest {
Phone name;
Fortest(Phone name) {
this.name = name;
}
public String handleUser(User user) {
String ph = name.getA();
if(ph.equalsIgnoreCase("test")){
return "done";
}
return "failed";
}
}
public class TestFortest {
#Before
public void before() {
name = ; //...
subject = new Fortest(name);
}
}
Now the tests are fairly simply:
public void whenTestModeIsEnabledThenReturnDone() {
setPhoneIntoTestMode();
String actual = subject.handleUser(null);
assertEquals(actual, "done");
}
public void whenTestModeIsDisabledThenReturnFailed() {
setPhoneIntoLiveMode();
String actual = subject.handleUser(null);
assertEquals(actual, "failed");
}
The implementation of setPhoneIntoTestMode/setPhoneIntoLiveMode will depend on how complex Phone is. If it is complex than we would look at "facking" it in some way (mocks, stubs, etc). This could be a chunk of code you write, it could be using a tool like Mocketo.
If the Phone object is simple, and has or can have a "setA" method, then just use that.
I'm sure later you will need userdao. The same thing will be done at that point. Inject and mock/setup the object.
You don't. One of the rules of mocking is: you never mock entities or value objects. If you need to break this rule, it means that you probably have a design flaw.
If you need to mock a new, you'll need to pass a factory to the object, and then you mock the factory. A very common example of this is when you need to mock Date objects, which is very well explained in this other question: How to mock the default constructor of the Date class (check the first answer).
As a side note, calling an instance of Phone name...mmm that doesn't look right.
Class mocking is very easy using EasyMock. It makes use of cglib internally to perform class mocking. EasyMock can both mock interfaces and classes (class mocking). See documentation.
So, to get your Phone mock, just call createMock(Phone.class):
Phone phoneMock = createMock(Phone.class);
As Augusto stated, it is not really good design to make use of class mocking though. A better way would be to program towards interfaces and use a dependency injection framework.
So you need to do one of the following options to inject mocks into the fields name and userdao (I am going to assume that you can use the new Phone field instance instead of the one created in the method.
Do not call constructors in your code directly but instead use field injection via setters. This will allow your test to provided mocked instances of the two classes. If you must create a new instance in the method then consider using a factory which can be mocked.
Provide default scope setter methods for the two fields. These methods would be in place for test purposes only.
Use Refection to set the fields to mocked instances. An easy way to do this is with Spring's ReflectionTestUtils.
Once one of these is in place you can provide mocked instances (maybe using Mockito) to drive the behavior you wish to test. I would suggest that option 1 is the best if fesible, then option 3. However, the disadvantage to options 3 is that the test is dependant of the names of private fields.
Then...
Phone phone = Mockito.mock(Phone.class);
Mockito.when(phone.getA()).thenReturn("blah");
objectUnderTest.setPhone(phone);
objectUnderTest.handleUser(...);
Say my server exports the following procedure:
List listFiles(int userId);
I can't allow just any user to list files for a given user. They need to have authorization to do so.
My XML-RPC service uses basic auth to authenticate users.
What would be the recommended way to make the login credentials (the current user object) accessible to the procedure calls?
If you write your own XmlRpcServlet subclass (see http://ws.apache.org/xmlrpc/server.html section Basic Authentication for an example), you could stick the user credentials on a ThreadLocal (see http://java.dzone.com/articles/java-thread-local-%E2%80%93-how-use).
I discovered the solution. The key is to subclass the RequestProcessorFactoryFactory and specify to the Handler that you wish to use your subclass.
http://ws.apache.org/xmlrpc/apidocs/org/apache/xmlrpc/server/RequestProcessorFactoryFactory.RequestSpecificProcessorFactoryFactory.html
protected java.lang.Object getRequestProcessor(java.lang.Class pClass,
XmlRpcRequest pRequest)
throws XmlRpcException
Subclasses may override this method for request specific configuration. A typical subclass will look like this:
public class MyRequestProcessorFactoryFactory
extends RequestProcessorFactoryFactory.RequestSpecificProcessorFactoryFactory {
protected Object getRequestProcessor(Class pClass, XmlRpcRequest pRequest) {
Object result = super.getRequestProcessor(pClass, pRequest);
// Configure the object here
...
return result;
}
}
Parameters:
pRequest - The request object.
Throws:
XmlRpcException
Here's an example telling the default handler to use your Factory:
public class EchoServer {
public static void main(String[] args) throws Exception {
WebServer webServer = new WebServer(8080);
XmlRpcServer xmlRpcServer = webServer.getXmlRpcServer();
PropertyHandlerMapping phm = new PropertyHandlerMapping();
EchoService echo = new EchoServiceImpl();
phm.setRequestProcessorFactoryFactory(new MyRequestProcessorFactoryFactory());
phm.setVoidMethodEnabled(true);
phm.addHandler(EchoService.class.getName(), EchoService.class);
xmlRpcServer.setHandlerMapping(phm);
XmlRpcServerConfigImpl serverConfig = (XmlRpcServerConfigImpl) xmlRpcServer.getConfig();
serverConfig.setEnabledForExtensions(true);
serverConfig.setContentLengthOptional(false);
webServer.start();
}
}
So to answer my original question, I would create a RequestProcessorFactoryFactory as folows:
public class MyRequestProcessorFactoryFactory
extends RequestProcessorFactoryFactory.RequestSpecificProcessorFactoryFactory {
protected Object getRequestProcessor(Class pClass, XmlRpcRequest pRequest) {
Object result = super.getRequestProcessor(pClass, pRequest);
// Configure the object here
ClassOfObjectBeingExposedViaXmlRpc obj = (ClassOfObjectBeingExposedViaXmlRpc) result;
XmlRpcHttpRequestConfig httpRequest = (XmlRpcHttpRequestConfig) pRequest.getConfig();
MyUserClass user = authenticateSomehow(httpRequest.getBasicUserName(), httpRequest.getBasicPassword());
obj.setUser(user);
return result;
}
}
Thus the XML-RPC exposed object will be able to reference the authenticated user and authorize methods accordingly.