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);
Related
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
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.)
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
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.
Say I have an interface IFoo which I am mocking. There are 3 methods on this interface. I need to test that the system under test calls at least one of the three methods. I don't care how many times, or with what arguments it does call, but the case where it ignores all the methods and does not touch the IFoo mock is the failure case.
I've been looking through the Expect.Call documentation but can't see an easy way to do it.
Any ideas?
You can give rhino mocks a lambda to run when a function get's called. This lambda can then increment a counter. Assert the counter > 1 and you're done.
Commented by Don Kirkby:
I believe Mendelt is referring to the Do method.
Not sure this answers your question but I've found that if I need to do anything like that with Rhino (or any similiar framework/library), anything that I didn't know how to do upfront, then I'm better just creating a manual mock.
Creating a class that implements the interface and sets a public boolean field to true if any of the methods is called will be trivially easy, you can give the class a descriptive name which means that (most importantly) the next person viewing the code will immediately understand it.
If I understood you correctly you want to check that the interface is called at least once on any of three specified methods. Looking through the quick reference I don't think you can do that in Rhino Mocks.
Intuitively I think you're trying to write a test that is brittle, which is a bad thing. This implies incomplete specification of the class under test. I urge you to think the design through so that the class under test and the test can have a known behavior.
However, to be useful with an example, you could always do it like this (but don't).
[TestFixture]
public class MyTest {
// The mocked interface
public class MockedInterface implements MyInterface {
int counter = 0;
public method1() { counter++; }
public method2() { counter++; }
public method3() { counter++; }
}
// The actual test, I assume you have the ClassUnderTest
// inject the interface through the constructor and
// the methodToTest calls either of the three methods on
// the interface.
[TestMethod]
public void testCallingAnyOfTheThreeMethods() {
MockedInterface mockery = new MockedInterface();
ClassUnderTest classToTest = new ClassUnderTest(mockery);
classToTest.methodToTest();
Assert.That(mockery.counter, Is.GreaterThan(1));
}
}
(Somebody check my code, I've written this from my head now and haven't written a C# stuff for about a year now)
I'm interested to know why you're doing this though.