CDI Extensions: Can I expose one interface in two scopes? - unit-testing

I have an interface in a unit testing framework: CDIMocker. I'm currently using an interceptor to allow mocking in a CDI container. It's an experiment - one of a couple of approaches to unit testing I'm considering. (The other main contender is to use constructor and method injection for all beans and unit test outside CDI - in which case this work becomes more a learning exercise in CDI Extensions).
I have two custom scopes - TestClassScoped and TestMethodScoped. My JUnit4 custom runner wraps the appropriate Class and Method blocks in statements that start and stop these scopes as needed. It also starts an instance of Weld-SE if needed. It knows if it's in CDI because the Extension remembers.
The mocker interface is the same wherever it us used. It would be nice to expose it in both scopes, so I could
// Sadly Static Injection currently doesn't work, but if it did
#Inject #TestClassScoped
private static CdiMocker s_classScopedMocker
#Inject #TestMethodScoped
private CdiMocker m_methodScopedMocker
There are other obvious ways. I currently have a factory method on a singleton outside CDI that can return either of these instances (ThreadLocal), or create a new short lived one. I have also had success creating two concrete classes and declaring different scopes on them.
I've tried using Producer Methods annotated as above, but no luck. Perhaps a simple mistake, perhaps a misunderstanding.
#Produces #TestClassScoped
public CdiMocker getClassScopedMockerForCdi()
{
return getTestClassContext().getMocker();
}
#Produces #TestMethodScoped
public CdiMocker getMethodScopedMockerForCdi()
{
return getTestMethodContext().getMocker();
}
I thought from some part of the CDI documentation it was possible to declare scopes on injection points as I have done, but I note that the Instance<> interface does not allow me to select() using scoped annotation so maybe that is wrong.
I could provide two qualifiers. Can an annotation be a Qualifier and a Scope at the same time?
Another idea would be to have my extension provide two Bean<CdiMocker>, both exposing the same class but in different scopes. They could also provide custom create() and destroy() because the CdiMocker instances are managed by my two custom Contexts. The impression I get of CDI is that a given Class can only live in one Scope, so would this be Wrong?
Any suggestions on what is best?
Thanks
- Richard
(I'd love to open source the result, but have done enough in work time I'd have to ask so not likely. The business argument would be public review. I use an Interceptor now with the disadvantage that it has to be left in place, but wonder if I could achieve something by intercepting the bean lifecycle in the extension. We can use Alternatives for things like the comms layer that talks to our legacy app server, but for some things a single unit test wants a custom mock and Alternatives are too global.)

I've created
#Qualifier
#Target({TYPE, METHOD, PARAMETER, FIELD})
#Retention(RUNTIME)
#Documented
public #interface Scoped
{
Class<? extends Annotation> value();
}
I currently have two Bean implementations. Relevant (unusual) parts are:
/**
* A Bean<> implementation for the CdiMocker beans
*/
class MockerBean implements Bean<CdiMocker>
{
private final class ScopedAnnotation extends AnnotationLiteral<Scoped> implements Scoped
{
private static final long serialVersionUID = 1L;
public Class<? extends Annotation> value() { return m_context.getScope(); }
}
private final CdiMockContextControl m_context;
public MockerBean(CdiMockContextControl context)
{
m_context = context;
}
The bean class is CdiMocker.class
#Override
public Class<?> getBeanClass()
{
return CdiMocker.class;
}
The Qualifiers include my ScopedAnnotation defined above. I've also included Default and Any. Maybe I need to remove these?
The scope is returned by my CdiMockContextControl interface.
#Override
public Class<? extends Annotation> getScope()
{
return m_context.getScope();
}
Type is my CdiMocker interface
#Override
public Set<Type> getTypes()
{
Set<Type> types = new HashSet<Type>();
types.add(CdiMocker.class);
types.add(Object.class);
return types;
}
Because the lifecycle is managed elsewhere I return the existing one.
#Override
public CdiMocker create(CreationalContext<CdiMocker> arg0)
{
return m_context.getMocker();
}
... and don't destroy it.
#Override
public void destroy(CdiMocker instance, CreationalContext<CdiMocker> ctx)
{
// It is managed by the Context, so I must not destroy it here.
ctx.release();
}
The solution is using Qualifiers, so I suppose it is now "Correct". I assume I can use lifecycle management in this way?
My test class (which my Runner instantiates using CDI) has
/**
* My CDI Extension makes a Mocking Context available in the Test Method Scope.
* This will be created before every test method, then destroyed afterwards.
*/
#Inject #Scoped(TestMethodScoped.class)
private CdiMocker m_testMethodMocker;
Richard

Related

How to handle different return type of a method in then Return? [duplicate]

I'm using mockito 1.9.5.
I have the following code:
public class ClassA {
public List<? extends MyInterface> getMyInterfaces() {
return null;
}
public static void testMock() {
List<MyInterface> interfaces = new ArrayList<>();
ClassA classAMock = mock(ClassA.class);
when(classAMock.getMyInterfaces()).thenReturn(interfaces);
}
I get a compilation error for the thenReturn(interfaces) saying:
"The method thenReturn(List<capture#1-of ? extends MyInterface>) in the type
OngoingStubbing<List<capture#1-of ? extends MyInterface>> is not applicable for the arguments
(List<MyInterface>)"
However, when I use the thenAnswer method of mockito, I don't get the error. Can anyone tell me what's going on? Why do I get the error when I use the thenReturn method?
Is there any other way to solve this problem when ClassA is provided by a 3rd party and cannot be modified?
EDIT : Starting from Mockito 1.10.x, generics types that are embedded in the class are now used by Mockito for deep stubs. ie.
public interface A<T extends Observer & Comparable<? super T>> {
List<? extends B> bList();
T observer();
}
B b = deep_stubbed.bList().iterator().next(); // returns a mock of B ; mockito remebers that A returns a List of B
Observer o = deep_stubbed.observer(); // mockito can find that T super type is Observer
Comparable<? super T> c = deep_stubbed.observer(); // or that T implements Comparable
Mockito tries its best to get type information that the compiler embeds, but when erasure applies, mockito cannot do anything but return a mock of Object.
Original : Well that's more of an issue with generics than with Mockito. For generics, you should read what Angelika Langer wrote on them. And for the current topic, i.e. wildcards, read this section.
But for short, what you could use is the other syntax of Mockito to help with your current situation :
doReturn(interfaces).when(classAMock).getMyInterfaces();
Or with the BDD aliases :
willReturn(interfaces).given(classAMock).getMyInterfaces();
Nevertheless, you could write wrappers that are more generic friendly. That will help future developers working with same 3rd party API.
As a side note: you shouldn't mocks type you don't own, it can lead to many errors and issues. Instead you should have some wrapper. DAO and repositories for example represent such idea, one will mock the DAO or repository interface, but not the JDBC / JPA / hibernate stuff. There are many blog posts about that:
http://davesquared.net/2011/04/dont-mock-types-you-dont-own.html
http://blog.8thlight.com/eric-smith/2011/10/27/thats-not-yours.html
https://web.archive.org/web/20140923101818/http://freshbrewedcode.com/derekgreer/2012/04/01/tdd-best-practices-dont-mock-others/
...
Another solution (albeit less readable) is to qualify the static method call of when to bind the wildcard:
Mockito.<List<? extends MyInterface>>when(classAMock.getMyInterfaces()).thenReturn(interfaces);

How to mock final field? mockito/powermock

I have same class
class MyCalss{
final static SomeClass field = new SomeClass();
...
}
I should to mock instance of MyCalss. This mock should contain field like real object.
How can I achieve it?
Mocking operates on methods and interfaces, not fields; furthermore, it operates on instance members, not static members. Mockito and Powermock are not the right tools to solve this problem.
Though you can use reflection to set final fields, you're effectively working around your own declaration, and are subject to the limitations and hazards of JLS 17.5.3.
A better design would be to rewrite the method in the system under test to inject its SomeClass dependency:
public void methodUnderTest() {
methodUnderTest(MyClass.field);
}
/** Package-visible for testing. Test this method instead. */
void methodUnderTest(SomeClass someClass) {
someClass.firePhotonTorpedoes();
}
You can use a framework that allows for mocking calls to constructors such as JMockit or Powermock.
Powermock
JMockit

Should I initialize mock objects in setup or in the test case?

In unit testing with help of mock/fake objects, I wonder whether it's more preferable to initialize the mocks in SetUp or in the test method itself, if my test class contains methods that test the same class (and thus, fake object needed should be the same for all test case). Something like this:
class FooTests
{
Mock<IBar> mockBar;
Foo fooUnderTest;
[SetUp]
public void Setup()
{
mockBar = new Mock<IBar>();
fooUnderTest = new fooUnderTest(mockBar.Object);
}
[Test]
public void MyTest()
{
//setup mock methods
mockBar.SetUp( ... )
//test
fooUnderTest.TestSomething()
//assert something here
}
}
It seems that this will prevent us from duplicating code to mockBar and fooUnderTest in each test case, but the downside is that I have to declare class variables mockBar and fooUnderTest (or is this really a downside?), and it will be problematic if I want to have some special setup (for example, if in some testcase I want to overriede some of the virtual methods of Foo). Any suggestion what is the best practice?
If there is some common setup shared by all tests in a suite/fixture (including setting up some expectations on mock collaborators), MOVE to a Setup method. (Ditto for incidental details that are not relevant to the reader within the test)
If one test case wants to extend common setup, add the specific setup inline within test-case itself
If one test case wants a different setup (inspite of significant overlap), MOVE to different test suite and figure out some other mechanism to share setup (e.g. via composition, utility methods, Object Mothers, etc.)

What do you call an inner class used for testing?

Our team has members who are just ramping up on unit testing and we're struggling with some terminology. I'd like to determine a name for a particular pattern. I'm hoping there's one that's already embraced by other developers, but if not, I'd like to come up with one that's descriptive and will make talking about test strategies easier.
This pattern is used quite a bit for testing abstract methods, but is also handy when an object creates a new object (for cases where DI doesn't work or isn't desired). The basic pattern is to use an inner class that extends the class under test to expose protected methods.
Consider the following code (which is pseudocode, based on Java, but should translate to most languages):
The class to test:
public class MyClass {
public void send() {
//do something
}
protected MailMessage createNewMailMessage() {
return new MailMessage();
}
}
The test:
public class MyClassTest {
private MyClass myClass = new TestableMyClass();
private MailMessage mockMessage = mock(MailMessage.class);
public void setup() {
((TestableMyClass)myClass).setMailMessage(mockMessage);
}
// Do some tests //
private class TestableMyClass extends MyClass {
private MailMessage mailMessage;
public void setMailMessage(MailMessage mailMessage) {
this.mailMessage = mailMessage;
}
protected MailMessage createNewMailMessage() {
return mailMessage;
}
}
}
So, what do you call this pattern? TestableMyClass a "Mock" object, but since it's not managed by a mocking framework, it seems like there should be another term to describe this pattern. Any suggestions or ideas?
I'd call it a stub. As you said, it's not a true "mock", since its behavior isn't being controlled by a mocking framework, but is a "true" object.
You don't need to use a mocking framework to call something a Mock/Stub object - your MyClassTest (which I'm assuming is supposed to extend MyClass) is just a Stub.
I don't think there's a particular name for the case where Mocks/Stubs are defined as inner classes of your test class - and in the particular example here, there's no reason for it to be an inner class - it could just be a package protected class (in the same file as MyClassTest or in its separate file..)
Mock contains test assertions.
Stub provides simple hard-coded values to make the test work.
Fake provides complex behavior/answers.
I usually add two underscores prefixing the inner class for testing so it doesn't show up in auto-complete, e.g. '__TestableMyClass'. Also if you are using Mockito you should be stubbing like so
MyClass myClass = mock(MyClass.class);
when(myClass.createNewMailMessage()).thenReturn(mockMessage);

Unit Testing using Mockito or JMock

Unit Testing:
I have the following classes
public class BImpl extends AImpl
{
public BImpl(final C c)
{
super(c);
}
public String getInfo()
{
final String info = getInformation();
// Do all my logic here
return info;
}
}
public abstract class AImpl
{
public String getInformation()
{
// some logic...returns String.
}
}
I am trying to unit test the method getInfo() by using any of the mocking methods available either Mockito or JMock.
for example when using Mockito I am using this way:
final AImpl aImpl = mock(AImpl.class);
when(aImpl.getInformation()).thenReturn("ABC");
Now since I have to create an instance of BImpl the only way I can create is using the constructor available.
final BImpl bImpl = new BImpl (C);
bImpl.getInfo();
when it calls into the getInfo() method and it tries to call getInformation(), it isn't calling the mocked object but calling the actual one.
What is the good way to test this method.
Is there any other way I can create an instance of BImpl without going by the constructor that I have given above?
Thanks!!
IMHO it's not a problem with mocking libraries but with your design. You want to test getInfo() method by mocking getInformation() on which it depends. Unit testing a method mocking all its dependencies is a right way to go and all mocking frameworks support it pretty well. So why you experience these problems?
Because you have chosen inheritance where composition was actually needed. You are abusing inheritance to implement uses relationship, whereas it should have been composition. Inheriting from a class just to have a convenient access to its methods is asking for trouble. Think of extending EntityManager by every repository/DAO...
You should refactor your code first so that BImpl has AImpl and the latter one is injected somehow. Then you can let some DI framework to perform the injection in production code (or do it yourself) with real implementation while injecting mock in unit test.