I am using Mockito to write a simple unit test. I have a smiple abstract class which implements Runnable:
public abstract class MyRunnable implements Runnable {
#Override
public void run() {
doTask();
}
public abstract void doTask();
}
Then, a function under test uses MyRunnable:
public class MyService {
public void something() {
executor.execute(new MyRunnable() {
#Override
doTask() {
…
}
});
}
}
My test case, I want to test doTask() has run :
#Test
public void testSomething() {
…
ArgumentCaptor<MyRunnable> myCaptor = ArgumentCaptor.forClass(MyRunnable.class);
verify(mockMyService).something(myCaptor.capture());
// get what has been captured
MyRunnable myRunnable = myCaptor.getValue();
//verify doTask() has run , but got ERROR.
verify(myRunnable).doTask();
}
My test case throw the following error:
org.mockito.exceptions.misusing.NotAMockException:
Argument passed to verify() is of type and is not a mock!
The error complains that verify() only accept mocked object. Then, how can I verify/test that the captured MyRunnable object has run doTask() with Mockito?
If you have control over your codebase, you can make your code testable with Mockito by moving any code that uses the new keyword into a separate Factory class like so...
public class MyService {
private MyRunnableFactory = factory;
public MyService(MyRunnableFactory factory) {
this.factory = factory;
}
public void something() {
executor.execute(factory.createInstance());
}
}
Then your test can simply inject a Mock of the factory which you can verify its behaviour/interactions
#Mock MyRunnableFactory factory;
#Mock MyRunnable myRunnable;
#Test
public void testSomething() {
when(factory.createInstance()).thenReturn(myRunnable);
// method under test
MyService service = new MyService();
service.something();
verify(myRunnable).doTask();
}
I use a rule of thumb that classes that creates objects, shouldn't have any business logic, so you don't have these testing headaches. This is essentially the Single Responsibilty Principal
You can't do this with Mockito because MyRunnable is created by the code under test. But you may have a look at PowerMock because it allows you to mock the constructor: https://github.com/jayway/powermock/wiki/MockConstructor
Related
There is a Adapter class which calls another legacyService and legacyService calls legacyDao and I want to mock the Legacy service calls.
In the below code SomeBean is returned as null instead of one the one that i created and passed in thenReturn. What could be the issue here?Please help I am new to mocking framework.
public class AdapterImpl implements Adpater{
//Injected through setter or constructor injection
private LegacyService legacy;
public SomeBean myMethod(){
CommonUtils.someStaticMethod()
return legacy.legacyService();
}
}
public class LegacyServiceImpl implements LegacyService{
//Injected through setter or constructor injection
private LegacyDAO ldao;//LegacyDAO is an interface
public SomeBean legacyService(){
return ldao.legacyDAO();
}
}
Test class
#RunWith(PowerMockRunner.class)
#PrepareForTest({CommonUtils.class})
public class AdapterImplTest{
#Mock private LegacyServiceImpl legacyService;
private LegacyDAO legacyDAO;
#Before
public void before(){
MockitoAnnotations.initMocks(this);
}
#Test
public void myMethodTest(){
PowerMockito.mockStatic(CommonUtils.class);
PowerMockito.when(CommonUtils.someStaticMethod()).thenReturn(someString());
legacyDAO = PowerMockito.mock(LegacyDAO.class);
SomeBean bean = new SomeBean(sometring1,somestring2);
PowerMockito.when(legacyDAO.legacyDAO().thenReturn(bean);//I am mocking interface method implementation
legacyService.setLegacyDAO(legacyDAO);
PowerMockito.when(legacyService.legacyService().thenReturn(bean);//same bean as above
AdapterImpl impl = new AdapterImpl();
impl.setLegacyService(legacyService)
//Below method call is not returning the bean that I constructed above it is being returned as null
impl.myMethod();
}
}
The original code posted in the question has many typos like missing parentheses and semi-colons. When I correct them, and fill in some of the methods like AdapterImpl.setLegacyService(), the test passes.
Then, as suggested in my comment, I removed the mocking of LegacyDAO. That mock object should not be needed if LegacyServiceImpl.legacyService() is properly mocked. When I rerun the test, it again passes.
All of which leads me to believe that there is an issue with the injection of the mock LegacyService object into AdapterImpl
FYI here is my passing test code, showing my typo fixes and assumptions about methods not shown in the original question. Hope this helps!
#RunWith(PowerMockRunner.class)
#PrepareForTest({ AdapterImplTest.CommonUtils.class })
public class AdapterImplTest {
#Mock
private LegacyServiceImpl legacyService;
// private LegacyDAO legacyDAO; // removed, no need to mock
#Before
public void before() {
MockitoAnnotations.initMocks(this);
}
#Test
public void myMethodTest() {
PowerMockito.mockStatic(CommonUtils.class);
PowerMockito.when(CommonUtils.someStaticMethod()).thenReturn(someString());
// legacyDAO = PowerMockito.mock(LegacyDAO.class);
SomeBean bean = new SomeBean("sometring1", "somestring2");
// I am mocking interface method implementation
// PowerMockito.when(legacyDAO.legacyDAO()).thenReturn(bean);
// legacyService.setLegacyDAO(legacyDAO);
// same bean as above
PowerMockito.when(legacyService.legacyService()).thenReturn(bean);
AdapterImpl impl = new AdapterImpl();
impl.setLegacyService(legacyService);
// Below method call is not returning the bean that I constructed above
// it is being returned as null
impl.myMethod();
}
private String someString() {
return "hello";
}
public class SomeBean {
public SomeBean(String string, String string2) {
}
}
public interface LegacyService {
public SomeBean legacyService();
}
public interface Adpater {
}
public class AdapterImpl implements Adpater {
// Injected through setter or constructor injection
private LegacyService legacy;
public SomeBean myMethod() {
CommonUtils.someStaticMethod();
return legacy.legacyService();
}
public void setLegacyService(LegacyServiceImpl legacyService) {
legacy = legacyService;
}
}
public class LegacyServiceImpl implements LegacyService {
// Injected through setter or constructor injection
private LegacyDAO ldao;// LegacyDAO is an interface
public SomeBean legacyService() {
return ldao.legacyDAO();
}
public void setLegacyDAO(LegacyDAO legacyDAO) {
ldao = legacyDAO;
}
}
public class LegacyDAO {
public SomeBean legacyDAO() {
return null;
}
}
public static class CommonUtils {
public static String someStaticMethod() {
return "in CommonUtils.someStaticMethod()";
}
}
}
Let's say I have a dagger 2 module as follows,
#Module
interface Creator {
MyClass create();
}
and I am using it to create an instance of MyClass
class Instantiator {
void doSomething(){
MyClass clazz = DaggerCreator.create().create();
// do things with clazz
}
}
It seems to me that I cannot effectively test the doSomething method in Instantiator because I cannot provide a mock for MyClass.
Am I wrong? If not are we supposed to use Dagger instantiation sparingly?
You are correct in saying that it is hard to test use of a Component injector, since this is a static method. But harder than what? Here is the same method using instantiation:
class Instantiator {
void doSomething(){
MyClass clazz = new MyClass();
// do things with clazz
}
}
still hard to test, right?
The point is to use as few Component (injectors) as possible and to pass in dependencies in the constructor for your objects. Dagger 2 makes resolving the dependencies in the constructor easy. This thereby makes testing easy since you can pass in mock object in a constructor.
Let's refactor the code you wrote to be testable. Assume that MyClass contains a single method, fireLazers() that you want to test is being invoked inside Instantiator's doSomething() method:
public class DoerOfSomething {
private final MyClass myClass;
#Inject
public DoerOfSomething(MyClass myClazz) {
this.myClass = myClazz;
}
public void doSomething() {
myClass.fireLazers();
}
}
Now you can write a test like this using a mock object:
public void DoerOfSomethingTest {
//mocks
MyClass mockMyClass;
//system under test
DoerOfSomething doerOfSomething;
#Before
public void setUp() {
mockMyClass = Mockito.mock(MyClass.class);
}
#Test
public void whenDoSomething_thenInteractsWithMyClass() {
//arrange
doerOfSomething = new DoerOfSomething(mockMyClass);
//act
doerOfSomething.doSomething();
//assert
verify(mockMyClass).fireLazers();
}
}
Of course, you will now need to inject DoerOfSomething into the top level class where you are injecting, but now you can be certain that the object you are injecting is functioning as expected because it is testable. Your code for using Dagger looks a bit unusual but I'll use your idioms for the sake of parity between the question and the answer.
class Instantiator {
private final DoerOfSomething doerOfSomething;
Instantiator() {
doerOfSomething = DaggerCreator.create().create();
}
void doSomething() {
doerOfSomething.doSomething();
}
}
I'm trying to unit test code that runs as callback in a Consumer functional interface.
#Component
class SomeClass {
#Autowired
private SomeInteface toBeMockedDependency;
public method() {
toBeMockedDependency.doSomething(message -> {
// Logic under test goes here
// (implements java.util.function.Consumer interface)
...
});
}
}
#RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
#InjectMocks
private SomeClass someClass;
#Mock
private SomeInteface toBeMockedDependency;
#Test
public void testMethod() {
...
someClass.method();
...
}
}
Essentially I want to provide the tested code some tested "message" via "toBeMockedDependency".
How can the "toBeMockedDependency" be mocked to provide a predefined message?
Is it the right approach?
Don't try to make toBeMockedDependency automatically call your functional interface. Instead, use a #Captor to capture the anonymous functional interface, and then use your test to manually call it.
#RunWith(MockitoJUnitRunner.class)
public class SomeClassTest {
#InjectMocks
private SomeClass someClass;
#Mock
private SomeInteface toBeMockedDependency;
#Captor
private ArgumentCaptor<Consumer<Message>> messageConsumerCaptor;
#Test
public void testMethod() {
someClass.method();
verify(toBeMockedDependency).doSomething(messageConsumerCaptor.capture());
Consumer<Message> messageConsumer = messageConsumerCaptor.getValue();
// Now you have your message consumer, so you can test it all you want.
messageConsumer.accept(new Message(...));
assertEquals(...);
}
}
I am using TestNG 6.8.8, Mockito 1.9.5 and PowerMock 1.5.4. When I mock a final void method, the test passes sometimes and fails sometimes with error UnfinishedStubbingException.
Is this a PowerMock bug?
public abstract class Parent implements Serializable {
protected abstract void validate();
public final void validateSomething() {
// some code here
}
}
#PrepareForTest({ Parent.class })
public class ParentTest {
#Test
public final void testSomeMethod() {
Parent parentObj = PowerMockito.mock(Parent.class);
doNothing().when(parentObj).validateSomething();
TestCodeThatResultsInCallToParentObj.validateSomething();
}
}
Error message:
org.mockito.exceptions.misusing.UnfinishedStubbingException:
Unfinished stubbing detected here:
-> at org.powermock.api.mockito.internal.PowerMockitoCore.doAnswer(PowerMockitoCore.java:36)
E.g. thenReturn() may be missing.
Examples of correct stubbing:
when(mock.isOk()).thenReturn(true);
when(mock.isOk()).thenThrow(exception);
doThrow(exception).when(mock).someVoidMethod();
Hints:
1. missing thenReturn()
2. you are trying to stub a final method, you naughty developer!
at org.powermock.api.mockito.internal.invocation.MockitoMethodInvocationControl.performIntercept(MockitoMethodInvocationControl.java:260)
You can use delegation and wrap the execution of that class in your class.
class ParentWrapper {
private final Parent delegate;
ParentWrapper(Parent delegate) {
this.delegate = delegate;
}
void validateSth() {
delegate.validateSth();
}
}
and now you can mock the ParentWrapper without any Powermock.
I am using Fluent NHibernate and trying to do unit testing. Now I have a base test class which looks as follows:
[TestClass]
public abstract class BaseTest<TEntity> where TEntity : IBaseModel
{
private const string testDbFile = "test.db";
private static ISessionFactory sessionFactory;
protected static ISession session;
[TestMethod]
public void configureDB()
{
try
{
if (sessionFactory == null)
{
sessionFactory = Fluently.Configure()
.Database(SQLiteConfiguration.Standard
.UsingFile(testDbFile))
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<AdminTest>())
.ExposeConfiguration(BuildSchema)
.BuildSessionFactory();
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException.Message);
}
}
private static void BuildSchema(Configuration config)
{
new SchemaUpdate(config).Execute(false, true);
}
[TestMethod]
public void sessionCreated()
{
session = sessionFactory.OpenSession();
}
[TestMethod]
public virtual void AddEntity_EntityWasAdded()
{
var entity = BuildEntity();
InsertEntity(entity);
session.Evict(entity);
var reloadedEntity = session.Get<TEntity>(entity.Id);
Assert.IsNotNull(reloadedEntity);
AssertAreEqual(entity, reloadedEntity);
AssertValidId(reloadedEntity);
}
There are also other methods which update and delete an entity. And I have AdminTest class which inherits BaseTest. In AdminTest I have following method:
[TestClass]
public class AdminTest : BaseTest<Admin>
{
[TestMethod]
public void SelectWorks()
{
IList<Admin> admins = session.QueryOver<Admin>().List();
Assert.AreNotEqual(0, admins.Count);
}
}
Here I always have exception, because session is null. Maybe I am wrong in the way of thinking how visual studio performs unit tests (I am newbie in it)?
Now I think like that, visual studio works in the following way
runs test-methods from BaseTest (there it configures database and creates session)
runs selectWorks method. Here I was thinking it should use session from BaseTest
Could you explain what is wrong in my way of thinking? And I want to be able to query from child classes, what is the right way of doing it?
Thanks, any help is appreciated, .
I would suggest using [TestInitialize] and [TestCleanup] in your abstract base class and doing something like the following:
[TestInitialize]
public void TestInitialize()
{
Console.Out.WriteLine("Get a ISession object");
}
[TestCleanup]
public void TestCleanup()
{
Console.Out.WriteLine("Dispose ISession");
}
Then in your child classes continue to do what you are doing:
[TestMethod]
public void DoDbWork()
{
Console.Out.WriteLine("Running a query via nhibernate");
}
You really just want to ensure you have a clean session for each test. The attributes for TestInitialize and TestCleanup will run before and after each unit test. Here is the documentation for those attributes.
To ensure your ISession is in the right state,follow something like this.