New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constructor injection doesn't support @Tested fields from base class #479

Closed
tuegeb opened this Issue Nov 18, 2017 · 4 comments

Comments

2 participants
@tuegeb

tuegeb commented Nov 18, 2017

Please provide the following information:

  • Version of JMockit that was used: 1.32/1.36

  • Description of the problem:
    Constructor injection doesn't support @tested fields from a test base class because the order of the fields matters (first the @tested type, followed by fields that are annotated with @Injectable or @tested which are used to construct the tested type). Below test fails with

java.lang.IllegalStateException: Missing @Injectable for field "DIDependency diDep" in TypeWithDIAndOtherDependencies


public class Dependency {}

import org.springframework.stereotype.Service;
@Service
public class DIDependency {
}

public class TypeWithDependencies {
	public Class<?> clazz;
	public DIDependency diDep;
	public Dependency dep;
	public TypeWithDependencies(Class<?> clazz, DIDependency diDep, Dependency dep) {
		this.clazz = clazz;
		this.diDep = diDep;
		this.dep = dep;
	}
}

import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class TypeWithDIAndOtherDependencies {
	@Autowired
	public DIDependency diDep;
	public TypeWithDependencies type;
	@PostConstruct
	public void init() {
		type = new TypeWithDependencies(getClass(), diDep, new Dependency());
	}
}

import mockit.Injectable;
import mockit.Tested;
public abstract class DIBasedTest {
	@Tested
	protected TypeWithDependencies type;
	@Injectable
	protected DIDependency diDep;
}

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertSame;
import mockit.Tested;
public final class Test extends DIBasedTest {
	@org.junit.Test
	public void test(@Tested TypeWithDIAndOtherDependencies primaryType) {
		assertNotNull(primaryType.diDep);
		assertNotNull(type.dep);
		assertSame(type.diDep, primaryType.diDep);
		assertSame(type.clazz, primaryType.getClass());
	}
}

@tuegeb tuegeb changed the title from Constructor injection support doesn to Constructor injection support doesn't support tested fields from base class Nov 18, 2017

@tuegeb tuegeb changed the title from Constructor injection support doesn't support tested fields from base class to Constructor injection doesn't support tested fields from base class Nov 18, 2017

@tuegeb tuegeb changed the title from Constructor injection doesn't support tested fields from base class to Constructor injection doesn't support @Tested fields from base class Nov 18, 2017

@rliesenfeld rliesenfeld added question and removed question labels Nov 19, 2017

@rliesenfeld rliesenfeld self-assigned this Nov 19, 2017

@tuegeb

This comment has been minimized.

Show comment
Hide comment
@tuegeb

tuegeb Nov 27, 2017

@rliesenfeld: Thanks for the enhancement.
Unfortunately the execution of the test fails with the following error message:

java.lang.IllegalArgumentException: No constructor in tested class that can be satisfied by available
tested/injectable values
public TypeWithDependencies(Class<?>, DIDependency, Dependency)
disregarded because no tested/injectable value was found for parameter "clazz"

Setting the attribute "fullyInitialized = true" has had no impact on the result. The same error was thrown, if the @Tested parameter was transformed into an instance field of the class Test.

Could you check it again, please?
Thank you in advance.

tuegeb commented Nov 27, 2017

@rliesenfeld: Thanks for the enhancement.
Unfortunately the execution of the test fails with the following error message:

java.lang.IllegalArgumentException: No constructor in tested class that can be satisfied by available
tested/injectable values
public TypeWithDependencies(Class<?>, DIDependency, Dependency)
disregarded because no tested/injectable value was found for parameter "clazz"

Setting the attribute "fullyInitialized = true" has had no impact on the result. The same error was thrown, if the @Tested parameter was transformed into an instance field of the class Test.

Could you check it again, please?
Thank you in advance.

@rliesenfeld

This comment has been minimized.

Show comment
Hide comment
@rliesenfeld

rliesenfeld Nov 27, 2017

Member

No, it's all as expected now. The @Tested TypeWithDependencies type field in the base test class cannot be initialized because the constructor needs three arguments, and none of which has any matching @Tested or @Injectable in the base test class. Before, there was a bug where a @Tested parameter in a test method was taking precedence over @Tested fields from the base test class, and the behavior was being different between @Tested fields and parameters. Now, it's the same behavior.

Basically, anything defined in the base test class cannot depend on stuff defined in a test class extending it (the opposite is true). So, the @Tested TypeWithDependencies field needs to have its dependencies satisfied within the scope of the base test class.

Member

rliesenfeld commented Nov 27, 2017

No, it's all as expected now. The @Tested TypeWithDependencies type field in the base test class cannot be initialized because the constructor needs three arguments, and none of which has any matching @Tested or @Injectable in the base test class. Before, there was a bug where a @Tested parameter in a test method was taking precedence over @Tested fields from the base test class, and the behavior was being different between @Tested fields and parameters. Now, it's the same behavior.

Basically, anything defined in the base test class cannot depend on stuff defined in a test class extending it (the opposite is true). So, the @Tested TypeWithDependencies field needs to have its dependencies satisfied within the scope of the base test class.

@tuegeb

This comment has been minimized.

Show comment
Hide comment
@tuegeb

tuegeb Nov 27, 2017

You are right, but I just can not understand why using fullyInitialized = true does not make any difference in this case.

tuegeb commented Nov 27, 2017

You are right, but I just can not understand why using fullyInitialized = true does not make any difference in this case.

@rliesenfeld

This comment has been minimized.

Show comment
Hide comment
@rliesenfeld

rliesenfeld Nov 27, 2017

Member

The error message should be clear enough: no tested/injectable value was found for parameter "clazz". fullyInitialized = true cannot possibly know which Class value to inject; test code needs to provide that.

Member

rliesenfeld commented Nov 27, 2017

The error message should be clear enough: no tested/injectable value was found for parameter "clazz". fullyInitialized = true cannot possibly know which Class value to inject; test code needs to provide that.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment