I have a method that contains the following code:
public void myMethod(){
final MyDto expectedtDto = new MyDto();
MyRepository reposWithMock = new MyRepository(){
protected MyDao createDao(){
return new MyDao() {
public MyDto someMethod(){
return expectedtDto;
}
};
}
};
reposWithMock.doSomethingWithDao();
}
MyRepository.createDao() is called from the constructor of MyRepository.
MyDao.someMethod() is called from MyRepository.doSomethingWithDao().
However, the MyDao().someMethod() returns null instead of the expectedDto
Any idea why this is?
For clarification, some real working code:
package nl.tests;
public class TestAnon {
static class MyDao {
private int value;
public MyDao(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
static class Repository {
private MyDao dao;
public Repository() {
dao = createDao();
}
protected MyDao createDao(){
return new MyDao( 4 );
}
public MyDao getDao(){
return dao;
}
}
public static void main(String[] args) {
final MyDao testDao = new MyDao(8);
Repository repos = new Repository() {
protected MyDao createDao() {
if ( testDao == null ) {
System.out.println( "Error ");
return new MyDao(0);
}
return testDao;
}
};
System.out.println( "Dao :" + repos.getDao().getValue() );
}
}
This results in :
Error
Dao :0
Some additional information: I currently (have to) work with java 1.4.
My development environment is Rational Application Developer 7.
Addendum, to the given (and accepted answer). For the below code I've made the createDao() method public :
public static void main(final String[] args) {
final MyDao testDao = new MyDao(8);
Repository repos = new Repository() {
public MyDao createDao() {
if ( testDao == null ) {
System.out.println( "Error ");
return new MyDao(0);
}
return testDao;
}
};
System.out.println( "Dao :" + repos.getDao().getValue() );
System.out.println( "Dao :" + repos.createDao().getValue() );
}
Returns:
Error
Dao :0
Dao :8
It fails in Java 1.4 because the field containing the local variable is not yet initialized when the super constructor for Repository is executed.
It works in Java 1.5 and later, because then the field is initialized before the super constructor is called.
In general it is bad style to call methods which may be overridden in subclasses in a constructor, because it leads to this kind of problems.
According to what you provided a quick test outputs MyDto#190d11 or similar. So I bet you left out some important code which is responsible for some variable name hiding.
Test.java
public class Test {
public static void main(String args[]) {
new Test().myMethod();
}
public void myMethod() {
final MyDto expectedtDto = new MyDto();
MyRepository reposWithMock = new MyRepository() {
#Override
protected MyDao createDao() {
return new MyDao() {
#Override
public MyDto someMethod(){
return expectedtDto;
}
};
}
};
reposWithMock.doSomethingWithDao();
}
}
MyDto.java
public class MyDto {}
MyRepository.java
public abstract class MyRepository {
protected abstract MyDao createDao();
public void doSomethingWithDao() {
System.out.println(createDao().someMethod());
}
}
MyDao.java
public abstract class MyDao {
public abstract MyDto someMethod();
}
Make sure you actually override the method you think you do. Your IDE or #Override should help.
Is MyDto a child of MyDao?
Your return a MyDto when the method indicates you return a MyDao.
Maybe that is a piece of the problem.
A second solution could be:
Put the expectedtDto in the inner-class instead of the method.
Martijn
Your code works for me. The only way I could see that expectedDto could be null within the anonymous inner class is if you're referencing it on another thread without proper synchronization.
The test-case you described works fine for me.
You should provide minimal but complete standalone test-case that illustrates the problem to get help.
Related
I am trying to play around with class instantiation and this.
In the below example, the testresult class will be instantiated and stored.
this will be used to pass that class instance as a parameter to another class.
Is this proper usage of this as the class is instantiated elsewhere?
Not sure why I see error as "The constructor testfail(new Handler(){}) is undefined".
Code snippet:
public class testmain {
private testresult tr;
private testfunc tf;
public testmain() {
tr = new testresult();
tf = new testfunc(tr);
}
}
public class testfunc {
private testresult storeit;
public testfunc(testresult inst) {
storeit = inst;
}
// this will be running as seperate thread running forever.
}
public class testresult {
private testfail tp;
public void function() {
tp = new testfail(this); //----> error new Handler(){} undefined
}
}
public class testfail {
public testfail(testresult tr) {
///
}
}
Edit : The error due to inner class
public class testresult {
private testfail tp;
private class test {
public void function() {
tp = new testfail(this); ----> error
// new Handler(){} undefined
}
}
}
As written, your code will compile. Because testfail accepts an argument of testresult, using this will work, even though it's awkward and not something one normally sees.
Unless you overrode your testfail constructor by introducing another constructor that accepted a Handler as an argument, this compilation failure is expected.
As an example:
public class testfail {
public testfail(testresult tr) {
///
}
public testfail(Handler hr) {
}
}
i am writing a integration test framework for my java application and i run into one issue i am not able to fix. Please let me explain:
The following code snippets are simplified classes for better visibility:
I got the following abstract class:
public abstract class AbstractTestModel<T extends AbstractTestModel> {
public T doSomething(){
return getThis();
}
public T getThis(){
return (T) this;
}
public <U extends AbstractTestModel<T>> U as(Class<U> type){
AbstractTestModel<T> obj = this;
if (obj.getClass().isAssignableFrom(type)){
return type.cast(obj);
}else{
throw new AssertionError("This (" + obj.getClass().getName() +")could not be resolved to the expected class " + type.getName());
}
}
}
And there are may concrete classes like this:
public class ConcreteTestModel1 extends AbstractTestModel<ConcreteTestModel1> {
public void doSomethingElse(){
}
}
I also wrote a Factory class. This factory downloads a JSON object from the server and instantiates one of the concret classes - depending on the JSON response. This concrete classes have many helper methods for testing the JSON response. The thing is, that the factory method always returns an "AbstractTestModel".
The integration test looks like this (simplified):
public class SomeTest {
TestModelFactory testModelFactory;
#Before
public void init(){
testModelFactory = new TestModelFactory();
}
#Test
public void someTest(){
AbstractTestModel anyModel = testModelFactory.createModel("someIdOfTheServer");
//ERROR: this does not work! Cannot resolve method doSomethingElse():
anyModel.doSomething().as(ConcreteTestModel1.class).doSomethingElse();
//as() method returns AbstractTestModel instead of ConcreteTestModel1
//this works:
AbstractTestModel as = anyModel.as(ConcreteTestModel1.class);
//this does not work:
ConcreteTestModel1 asConcreteTestModel1 = anyModel.as(ConcreteTestModel1.class);
}
}
The method as(Class type) should check if the given class is valid, cast "this" to the desired class and return it, but it always returns the AbstractTestModel.
If I make the "as" method static or if i get rid of the generic class like this...
public abstract class AbstractTestModel {
/*
Not possible to return the superclass anymore
public T doSomething(){
return getThis();
}
public T getThis(){
return (T) this;
}
*/
public <U extends AbstractTestModel> U as(Class<U> type){
AbstractTestModel obj = this;
if (obj.getClass().isAssignableFrom(type)){
return type.cast(obj);
}else{
throw new AssertionError("This (" + obj.getClass().getName() +")could not be resolved to the expected class " + type.getName());
}
}
}
... then it works fine, but of course i am not able to return the concrete class in all other methods any more.
Thank you for reading this long post.
Do you know what am i doing wrong here? Is there a solution for that?
Thank you for any tip and have a nice day!
Manuel
The problem is the compiler needs to infer the type at compile time. This code is mostly as provided, but I added some output in doSomethingElse for the sake of demonstration, and added ConcreteTestModelX extending ConcreteTestModel1 (Note I removed the type T from the as method to explore the way it interacted with generic typing in further exploratory testing).
public abstract class AbstractTestModel<T extends AbstractTestModel> {
public T doSomething() {
return getThis();
}
public T getThis() {
return (T) this;
}
public <U extends AbstractTestModel> U as(Class<U> type) {
if (getClass().isAssignableFrom(type)) {
return type.cast(this);
} else {
throw new AssertionError("This (" + getClass().getName()
+ ") could not be resolved to the expected class " + type.getName());
}
}
}
class ConcreteTestModel1 extends AbstractTestModel<ConcreteTestModel1> {
public void doSomethingElse() {
System.out.println("This is \"" + getClass().getSimpleName() + "\" doing something else");
}
}
class ConcreteTestModelX extends ConcreteTestModel1 {
}
And with this test
import org.junit.Test;
public class SomeTest {
#Test
public void someTest(){
AbstractTestModel<ConcreteTestModel1> anyModel = new ConcreteTestModel1();
ConcreteTestModel1 asConcreteTestModel1 = anyModel.as(ConcreteTestModel1.class);
asConcreteTestModel1.doSomethingElse();
AbstractTestModel anyModelX = new ConcreteTestModelX();
ConcreteTestModel1 asConcreteTestModelX = (ConcreteTestModel1)anyModelX;
asConcreteTestModelX.doSomethingElse();
}
}
Seems the problem you are having in the tests is that the variable you are using for the model is without generics, the compiler then strips the generics see this answer https://stackoverflow.com/a/18277337/7421645
Based on this I then created some new tests to explore:
import org.junit.Test;
public class SomeTest {
#Test
public void concreteTest(){
ConcreteTestModel1 asConcreteTestModel1 = getConcreteModel(new ConcreteTestModel1(), ConcreteTestModel1.class);
asConcreteTestModel1.doSomethingElse();
}
#Test
public void concreteExtendsTest(){
ConcreteTestModel1 asConcreteTestModelX = getConcreteModel(new ConcreteTestModelX(), ConcreteTestModelX.class);
asConcreteTestModelX.doSomethingElse();
}
private <T extends ConcreteTestModel1> T getConcreteModel(T anyModel, Class<T> classType) {
return anyModel.as(classType);
}
#Test
public void vanillaCastingTest(){
AbstractTestModel anyModelX = new ConcreteTestModelX();
ConcreteTestModel1 asConcreteTestModelX = (ConcreteTestModel1)anyModelX;
asConcreteTestModelX.doSomethingElse();
}
#Test
public void abstractGenericTest(){
AbstractTestModel<ConcreteTestModel1> anyModel = new ConcreteTestModel1();
ConcreteTestModel1 asConcreteTestModel1 = anyModel.as(ConcreteTestModel1.class);
asConcreteTestModel1.doSomethingElse();
}
#Test
public void failedGenericTest(){
AbstractTestModel anyModel = new ConcreteTestModel1();
ConcreteTestModel1 asConcreteTestModel1 = getAs(anyModel);
asConcreteTestModel1.doSomethingElse();
}
private ConcreteTestModel1 getAs(AbstractTestModel<ConcreteTestModel1> anyModel) {
return anyModel.as(ConcreteTestModel1.class);
}
}
Thanks to all answers, i could finally find the problem. It was actually quite easy:
The factory needed to return "AbstractTestModel<❓>" instead of just "AbstractTestModel". I've added the <❓> to every method who's returning the AbstractTestModel. Now it works just fine :) Thanks everyone. Couldn't find the answer without you.
I am writing unit tests for my akka actor classes. a field is being declared in abstract parent class and instantiated inside its constructor. During test case execution of child class that field is showing null. So how to instantiate the field from the test class.
Note: I am using partial Mocking also in testNG classes.
public abstract class ParentClass extends UntypedActor {
protected RestTemplate restTemplate;
protected ObjectMapper objMapper;
public ParentClass () {
super();
restTemplate = new RestTemplate();
objMapper = new ObjectMapper();
}
}
public class ChildClass extends ParentClass{
public ChildClass () {
super();
}
public void invoke(String json) throws Exception {
BeanClass bean = objMapper.readValue(json, Bean.class);
}
public String getJsonResponse(String json){
sysout("Get");
return "response";
}
}
public class ChildClassUnitTest {
#BeforeTest
public void setUp() throws Exception{
actorMock = PowerMock.createPartialMock(ChildClass.class,"getJsonResponse");
actorMock.getJsonResponse("req");
PowerMock.expectLastCall().andReturn("resp").anyTimes();
PowerMock.replay(actorMock);
}
#Test
public void testInvokePos() throws Exception{
ResponseClass response=actorMock.invoke("req");
System.out.println(response);
}
}
I am not known to json and I can only help with java code.
Please look at code below.
And my instance fields are initialized properly. They are not null. So I don't see any problem with your code atleast with what you have posted. Need to visit your UntypedActor class.
class ClassA
{
String x;
public ClassA ()
{
x = "Java";
}
}
abstract class ParentClass extends ClassA{
protected String restTemplate;
protected Integer objMapper;
public ParentClass () {
super();
restTemplate = " Language";
objMapper = 1;
}
}
class ChildClass extends ParentClass{
public ChildClass () {
super();
}
}
class HelloWorld
{
public static void main (String args[] )
{
ChildClass cc = new ChildClass ();
System.out.println ( cc.x + cc.restTemplate + cc.objMapper );
}
}
Output for the code is as expected
Java Language1
I want to change the object return from call to a constuctor
FROM
public class A {
public A(){
}
public String sayHello() {
return "hello";
}
public String foo() {
return "foo";
}
}
TO
public class AWrapped extends A {
private A wrapped;
public AWrapped() {
super();
}
public AWrapped(A pWrapped) {
wrapped=pWrapped;
}
public String foo() {
return wrapped.foo();
}
public String sayHello {
return "gday mate";
}
}
What i want to do is to change the object that is returned from a call
A a = new A();
a.sayHello() returns "gday mate"
a is an instaceof AWrapped
I understand that this would usually be done with a factory pattern but I dont have access to the code of A or the code that makes new A's. And there are 1000s of places that A can be created.
It seems that Aspectj might do the trick, but i dont know much about it, If AspectJ would do the trick how to I get around the infinite wrapping i need to know that its being consturcted from within and aspect so it doesnt wrapp it again.
Thanks for the help
Jon
If I understand you right you could do the following:
I've created three packages:
aspectj for the aspect and AWrapped.java
unknown for A.java (could also be Bytecode but then you have to use Load Time Weaving)
main to test A a = new A();
MyAspect to return the AWrapped object if a new() call is made on class A:
package aspectj;
import unknown.A;
#Aspect
public class MyAspect {
#Pointcut("call(unknown.A.new(..)) && !within(aspectj..*)")
public static void init(ProceedingJoinPoint pjp) {
}
#Around("init(pjp)")
public Object initAdvice(ProceedingJoinPoint pjp) throws Throwable{
Object ret = pjp.proceed();
return new AWrapped((A) ret);
}
}
For testing:
package main;
import unknown.A;
public class Main {
public static void main(String[] args) {
A a = new A();
System.out.println(a.sayHello());
}
}
This outputs:
gday mate
I'm having problems with counting method calls with Mockito. Problem is that the method whos calls I want to count is called in test class indirectly by other method. Here is the code:
public class ClassForTest {
private Integer value;
public void doSmth() {
prepareValue("First call");
prepareValue("Second call");
prepareValue("Third call");
System.out.println(value);
}
protected void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
}
And the test class:
public class ClassForTestTest extends TestCase {
#Test
public void testDoSmth() {
ClassForTest testMock = mock(ClassForTest.class);
doNothing().when(testMock).prepareValue(anyString());
testMock.doSmth();
verify(testMock, times(3)).prepareValue(anyString());
}
}
Having such exception:
Wanted but not invoked:
classForTest.prepareValue(<any>);
-> at org.testing.ClassForTestTest.testDoSmth(ClassForTestTest.java:24)
However, there were other interactions with this mock:
-> at org.testing.ClassForTestTest.testDoSmth(ClassForTestTest.java:21)
Any ideas please. Thanks in advance!
This will work. Using a spy calls the underlying method. Make sure value is initialized first.
#Test
public void testDoSmth() {
ClassForTest testMock = spy(new ClassForTest());
testMock.doSmth();
verify(testMock, times(3)).prepareValue(anyString());
}
public class ClassForTest {
private Integer value = 0;
public void doSmth() {
prepareValue("First call");
prepareValue("Second call");
prepareValue("Third call");
System.out.println(value);
}
protected void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
}
This is an indication that you need some refactoring to improve your design. A single class should be fully testable without needing to mock out pieces of it. Whatever pieces you feel need to be mocked out should be extracted into one or more collaborating objects. Don't fall into the trap of partial mocks. Listen to what the tests are telling you. Your future self will thank you.
You are mocking the tested class. Mocking is intended for the dependencies of a tested class, rather than the class itself.
I suspect what you want is Mockito.spy(). However, this is partial mocking which the Mockito Javadoc recommends against.
Alternatively, if you want to refactor for testability, you can do the following:
#Test
public void testDoSmth() {
Preparer preparer = mock(Preparer.class);
ClassForTest cft = new ClassForTest(preparer);
cft.doSmth();
verify(preparer, times(3)).prepareValue(anyString());
}
public class ClassForTest {
private final Preparer preparer;
public ClassForTest(Preparer preparer) {
this.preparer = preparer;
}
public void doSmth() {
preparer.prepareValue("First call");
preparer.prepareValue("Second call");
preparer.prepareValue("Third call");
System.out.println(preparer.getValue());
}
}
public class Preparer {
private Integer value = 0;
public void prepareValue(String msg) {
System.out.println("This is message: " + msg);
value++;
}
public Integer getValue() {
return value;
}
}