I am using junit and mokito to write unit test of my java program.
public MyClass {
private ClassA a;
public void process(ClassB b) {
if(b.method()) a = ClassA.builder().build();
}
}
Now I have write a MockClassA and MockClassB. But I don't know how to :
Pass a MockClassB instantiation to process function
How to verify whether private variable a is set successfully
Can anybody help?
You can use something like:
#Test
public void shouldDoSomething() {
// given
ClassB mock = Mockito.mock(ClassB.class);
Mockito.when(mock.method()).thenReturn(true);
MyClass classUnderTest = new MyClass();
// when
classUnderTest.process(mock);
// then
// Insert assertions
}
However, if your field is private you are unable to test it properly. You should provide a getter for this field if you want to make some assertions against it.
But remember that internal representation of MyClass should not be tested, only the behavior of it so maybe you want to try different approach
Related
I have this code in a method I´m unittesting
public void SomeMethod()
{
IMyLogger log = new Logger();
log.ConfigLogger(); // Trying to not call this method
//...some other code...
}
Where this is the Logger class
public class Logger : IMyLogger
{
public void ConfigLogger()
{
//Serilog logging code I´m trying to not call in my unittests.
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Debug()
.CreateLogger();
}
}
And this is the my unittest where I´m trying to mock away (not call the code inside of the ConfigLogger() method without luck.
public void Test()
{
var logger = A.Fake<IMyLogger>();
A.CallTo(() => logger.ConfigLogger()).DoesNothing(); //Not working..
}
So what I´m I missing here? Why do I think this should be just like this? Even though Serilog specialist give me a better way to unittest Serilog I would also like to find out how to "FakeItEasy a void method".
Your production code is still using a concrete instance of Logger. FakeItEasy cannot influence the behaviour of anything but FakeItEasy-created Fakes.
The pattern for use is:
create a Fake that your production code will use as a collaborator
configure the Fake
provide the Fake to an instance of the production class under test
execute the production code
optionally interrogate the Fake
As your production code is written now, there is no opportunity to inject a collaborator - it makes its own collaborator (log). In order to avoid calling Logger methods, you'll need to provide a way to inject an alternative IMyLogger.
You should avoid having to instantiate and configure your logger within the method.
Something like
public class SomeClass()
{
IMyLogger log;
public SomeClass(IMyLogger logger)
{
this.log = logger;
}
public void SomeMethod()
{
// code you want to test
}
}
Then just pass it into your class under test:
public void Test()
{
var logger = A.Fake<IMyLogger>();
var someClass = new SomeClass(logger);
// test someClass.SomeMethod()
}
I have following Java code that I want to test. What I am having difficulty is figuring out how do I verify that call to handleAppVersionRequest , actually constructs AppVersionResponse object. Is there any way to do that using Mockito?
Here code is code for method:
class MyClass {
public void handleAppVersionRequest(String dataStr,
final int dataChannelId) {
String ver = "1.0";
final AppVersionResponse resp = new AppVersionResponse(ver);
Timber.d("Sending data %s", resp.toString());
sendResponse(dataChannelId, getGson().toJson(resp));
}
}
And here is method for test:
#Test
public void testHandleAppVersionRequest() throws Exception {
MyClass presenter = Mockito.spy(new MyClass());
String versionRequestJson = "{\"command\":1}";
when(presenter.getGson()).thenReturn(gSon);
presenter.handleAppVersionRequest(versionRequestJson,0);
// How do I verify that AppResponse object was constructed?
verify(presenter,times(1)).sendResponse(anyInt(),anyString());
}
If you must test the creation of the object during a unit test, you can extract a factory, mock it for your test, and then verify that the create method is called on it.
At the same time, consider spending some time looking at some tutorials for Mockito and unit testing in general, like this one. You should choose one class that is going to be the 'system under test'. Don't spy or mock this class! Instead, pass in mocks as dependencies that you will use to test the behaviour of your class.
Here is a factory extracted from your MyClass:
class AppVersionResponseFactory {
AppVersionResponse create(String version) {
return new AppVersionResponse(version);
}
}
Then the refactored version of your class where the dependencies (Gson and the factory) are passed in through the constructor:
class MyClass {
//dependencies that can now be mocked!
private final AppVersionResponseFactory appVersionResponseFactory;
private final Gson gson;
//pass the mockable dependencies in the constructor of the system under test!
public MyClass(AppVersionResponseFactory appVersionResponseFactory, Gson gson) {
this.appVersionResposeFactory = factory;
this.gson = gson;
}
public void handleAppVersionRequest(String dataStr, final int dataChannelId) {
String ver = "1.0";
AppVersionResponse resp = AppVersionResponseFactory.create(ver);
Timber.d("Sending data %s", resp.toString());
sendResponse(dataChannelId, gson.toJson(resp));
}
}
Now your test looks something like this:
//mocks
AppVersionResponseFactory mockAppVersionResposeFactory;
Gson mockGson;
//system under test
MyClass myClass;
#Before
public void setUp() {
mockAppVersionResposeFactory = Mockito.mock(AppVersionResponseFactory.class);
mockGson = Mockito.mock(Gson.class);
myClass = new MyClass(mockGson, mockAppVersionResposeFactory);
}
#Test
public void testHandleAppVersionRequest() throws Exception {
String versionRequestJson = "{\"command\":1}";
myClass.handleAppVersionRequest(versionRequestJson, 0);
verify(appVersionResposeFactory).create("1.0");
}
Please note that although your question asks for a way to verify the construction of an object, a better test would probably test the final outcome of that method i.e., that sendResponse was called with the correct dataChannelId and correct JSON. You can use the same techniques in this answer to do that i.e., extracting a dependency (perhaps a ResponseSender?), passing it in the constructor for your MyClass, mocking it in the test, then calling verify on it.
Consider the following sample code:
#Stateless
public class MyBean {
private SomeHelper helper;
private long someField;
#PostConstruct
void init() {
helper = new SomeHelper();
someField = initSomeField();
}
long initSomeField() {
// perform initialization
}
public void methodToTest() {
helper.someMethod();
long tmp = 3 + someField;
}
}
And here is the test template, that I always use
public class MyBeanTest {
#Spy
#InjectMocks
private MyBean testSubject;
#Mock
private SomeHelper mockedHelper;
#Before
public void before() {
MockitoAnnotations.initMocks(this);
doReturn(1L).when(testSubject).initSomeField();
}
#Test
public void test() {
testSubject.methodToTest();
// assertions
}
}
The problem with testing methodToTest is that it needs field someField to be initialized. But the initialization is done in #PostConstruct method. And I can't run this method before call to testSubject.methodToTest(), because it will re-initialize helper. Also, I don't want to manually set up all the mocks. And I don't want to use reflection to set the someField, because that would make MyBeanTest vulnerable to MyBean refactoring. Can anybody propose, maybe better design to avoid situations like this?
A few notes:
Logic in initSomeField could be quite heavy (including calls to database), so I want to initialize it only once in a #PostConstruct method.
I don't want to create a setter for this field or widen its access modifier, because that would allow unwanted changes to my field.
If your test is in the same package as your class, then you can just call initSomeField directly, since it's package private. You can either do this in each individual test method, or in your #Before method, provided it runs after initMocks.
I am trying to mock ExecutorService and Executors from java.util.concurrent package.
I am able to get the mocked object if I try to get the object within the same class (test class) where I am mocking the object. However if I try to get the mocked object in a different class (the class I want to test) then it returns actual object from java.util.concurrent. Following is the code snippet.
The class I want to test:
public class MyClass
{
public void myMethod()
{
ExecutorService executorService = Executors.newFixedThreadPool(2, new MyThreadFactory());
for (int count = 0; count < 2; count++)
{
executorService.submit(new Thread());
}
}
}
class MyThreadFactory implements ThreadFactory
{
#Override
public Thread newThread(Runnable r)
{
return null;
}
}
My Test class looks like:
#RunWith(PowerMockRunner.class)
#PrepareForTest(Executors.class)
public class MyClassTest
{
#Test
public void testMyMethod()
{
prepareMocks();
//Code to get mocked object (See testMethod below)
}
private void prepareMocks()
{
ExecutorService executorService = PowerMock.createMock(ExecutorService.class);
EasyMock.expect(executorService.submit(EasyMock.anyObject(Runnable.class))).andReturn(null).anyTimes();
PowerMock.mockStatic(Executors.class);
EasyMock.expect(Executors.newFixedThreadPool(EasyMock.anyInt(), EasyMock.anyObject(ThreadFactory.class))).andReturn(executorService).anyTimes();
PowerMock.replay(executorService, Executors.class);
}
}
If MyClassTest.testMyMethod() is as below, it returns mocked oject.
#Test
public void testMyMethod()
{
prepareMocks();
//Following code reurned mocked instance of ExecutorService
ExecutorService executorService = Executors.newFixedThreadPool(2, new MyThreadFactory());
for (int count = 0; count < 2; count++)
{
executorService.submit(new Thread());
}
}
However if I change the test method to call myClass.myMethod() it returns actual instance instead of mocked instance in myMethod().
#Test
public void testMyMethod()
{
prepareMocks();
/*
* Within myClass.myMethod(), Executors.newFixedThreadPool() returns actual instance of ThreadPoolExecutor
* instead of mocked object
*/
MyClass myClass = new MyClass();
myClass.myMethod();
}
I am expecting to get a mocked instance of Executors/ExecutorService in myClass.myMethod.
Is this the expected behavior? Could anyone explain the behavior? Am I missing anything?
You need to let the class know that there is going to be a Mock incoming. In your #PrepareForTest(), try also including the class that is calling the static. This way you are telling it to mock the execution of the static, as well as telling it where this mock is going to be taking place. Try updating the #PrepareForTest({Executors.class, MyClass.class}).
When you have it so your test class is calling the static directly, you have the Executors.class in the #PrepareForTest() so it will know to "inject" that mock into the execution. When you call your other class, at runtime the class you are calling it doesn't know to use the mock version of your static class, which is why it is resorting to the original code that it knows about, not the mock outside its scope. Adding the class that CALLS the static object (the one you test), will allow the static mock you have to be hooked in when it is ran.
I have a public method that uses a local private method to get data from the Db.
private string SomeMethod(string)
{
...
Doing some operations
...
string data = GetDBData(string);
Doing some operations
...
}
I want to divert/isolate the private method GetDBData(string) using moles so my test will not require the DB.
Obviously, my question is: how to do it?
thank you
Uria
EDIT
Additional information:
i tried to change the method accessors both to public and internal protected,
in both cases i can now see the methods as moles.
BUT when running the test, the original method is still being used and not the detour I've implemented in the PexMethod.
You can try any of the following.
Make the method internal and add an attribute like this to the assembly:
[assembly: InternalsVisibleTo("<corresponding-moles-assembly-name>")]
Change the method access to protected virtual and then use a stub.
Refactor your class so that it gets an interface (IDataAccessObject) as a constructor parameter, SomeMethod being one of the methods of that interface, and then pass a stub of that interface to your class in test methods.
I figured it out
If i have the public MyClass with private SomeMethod
public class MyClass
{
private string SomeMethod(string str){}
}
if you want to mole the SomeMethod method you need to use AllInstances in the test method:
[PexMethod]
SomeMethod(string str)
{
MMyClass.AllInstances.SomeMethod = (instance, str) => { return "A return string"; };
}
notice that the lambda receives an instance parameter as the first parameter. I'm not sure what it's function is.