Play Framework 2.2.2 - Java -Testing Controllers With Mock Objects - java

Is anyone aware of any examples of testing a Java based Play Framework controller by setting mock objects?
I am using Spring in my Play project so all my controller methods are not static.
Testing the tradional way, Play shows my controller as having static methods and I just cant see a way of how I can inject mocks into my object
Result result = callAction(
controllers.routes.ref.LoginController.authenticate(),
fakeRequest().withFormUrlEncodedBody(TestUtils.SUCCESSFUL_LOGIN_MAP)
);
I have a number of services that need to be called in the LoginController and I would like to set those up as mocks
Any help is greatly appreciated
Thanks
Damien

I was looking for the solution of the same problem. So far the best result I was able to achieve is this:
public class MyObjectControllerTest{
private final MyObjectDAO dao = mock(MyObjectDAO.class);
private final MyObjectController controller = new MyObjectController(dao);
public static FakeApplication fakeApplication;
#BeforeClass
public static void startApp() {
fakeApplication = Helpers.fakeApplication();
Helpers.start(fakeApplication);
}
#AfterClass
public static void stopApp() {
Helpers.stop(fakeApplication);
}
#Test(expected = NotFoundException.class)
public void testFailWithUnknownMyObjectKey() throws Throwable {
when(dao.getByKey(any(UUID.class), any(UUID.class), any(Boolean.class))).thenReturn(null);
controller.get(CassandraUUIDs.timeBased());
}
#Test
public void testGetSuccess(){
MyObject deletedObject = MyObjectTestGenerator.generateMyObject();
deletedObject.setDeleted(true);
when(dao.getByKey(any(UUID.class), any(UUID.class), any(Boolean.class))).thenReturn(deletedObject);
try {
Result result = controller.get(CassandraUUIDs.timeBased());
assertThat(status(result)).isEqualTo(Http.Status.GONE);
assertThat(contentType(result)).isEqualTo(Http.MimeTypes.JSON);
assertThat(contentAsString(result)).isEqualTo(ErrorMsg.OBJECT_DELETED.toJson().toString());
} catch (MyObjectsException e) {
e.printStackTrace();
fail("Failed to send MyObject.get request.");
}
}
}
What I do here is instantiate an instance of the controller class and pass mocked DAO instance. Please note that I don't use static controller methods in my code as well.
One issue with this workaround I found so far is that Action (I have custom one) is not working. But Action can (and probably must) be tested separately.

Related

spring test mock static method globally

in spring test, I know I can mock static method(usually static util methods: generate id, get value from Redis) using Mockito like:
try (MockedStatic) {
}
but having to do this in every test method is ugly and cumbersome, is there any way to do it all(i am ok to have a single mocked behavior)
I am thinking maybe a junit5 extension, or Mockito extension, this seems like a common problem, I wonder if anyone tries something with any success.
try this
public class StaticClassTest {
MockedStatic<YourStatic> mockedStatic;
#Before
public void setup() {
mockedStatic = Mockito.mockStatic(YourStatic.class);
// if you want the same behavior all along.
mockedStatic.when(() -> YourStatic.doSomething(anyString())).thenReturn("TEST");
}
#Test
public void test_static() {
// write your test here
}
#After
public void teardown() {
mockedStatic.close();
}
}

Incapsulating class with static wrapper method is good idea?

I have been refactoring a huge method in the project I work and came up with this idea to create a validation service like this -
public class TrickyValidation {
String validationVariable1;
String validationVariable2;
String validationVariable3;
HashMap<String, Object> itemsMap;
Object dependentObject;
#Autowired
SpringService service;
public static boolean doTrickyValidation(HashMap<String, Object> itemsMap, Object dependentObject) {
return new TrickyValidation(itemsMap, dependentObject).validate();
}
private TrickyValidation(Object itemsMap, Object dependentObject) {
this.itemsMap = itemsMap;
this.someDependentObject = dependentObject;
init();
}
private boolean validate() {
// loads of logic for validation by using validationVaribales
return true;
}
private void init() {
// Some methods to extract thease variables from itemsMap, dependentObject etc..
this.validationVariable1 = service.get(dependentObject);
this.validationVariable1 = ...;
this.validationVariable1 = ...;
}
}
My goal what I want to do here is to Encapsulate everything as much as possible and use clean code principles.
I feel a bit here like fighting spring framework because I don't want
that "TrickyValidation" class would be #Servcie and belong to spring container. Will Autowired even work here?
Is it a good design? Most likely I will use this validation in a loop. I like this solution because when I have to validate things I just simply call one and only public static method of this class TrickyValidation.doTrickyValidation(map, obj)
Any suggestions are welcome on how to improve this, or why it's a bad idea.
This code probably won't work because in the init method of the object you're trying to access service which is not autowired into this instance. In general the autowiring works only for objects managed (created by) Spring.
In this case you create "manually" the object of class TrickyValidation...
IMO the better design is to split the "Validator" object that can be Spring managed and the Validation itself that is not spring based.
#Component
public class Validator {
#Autowired
private Service service;
public boolean doTrickyValidation(HashMap<String, Object> itemsMap, Object dependentObject) {
// resolve the validation strategy from the items passed to this method.
TrickyValidation validation = resolveTrickyValidation(itemsPam, dependentObject);
return validation.validate();
}
private TrickyValidation resolveTrickyValidation(...) {
// construct the proper validation strategy
// access service if you want
}
}

How to test FacesContext showing a message with JUnit

abort()-Method:
public void abort() {
LOG.info("some-text");
warning("some-text");
}
warning()-Method:
public void warning(String message) {
FacesContext.getCurrentInstance()
.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "INFO:", message));
}
I want to write a Test-Case for abort wich is just verifying that nothing has changed and a second Test-Case which is verifying that warning() is working.
I´m knowing this little two methods doesn´t need a Unit-Test but I want to know if it´s possible. UI-Test for showing the p:message is working well but I want to check the Caption, Typ and Message by Unittest before because it´s running much faster.
working solution with just using JUnit 4.11
Separate the content from warning() in a own class like this:
#Named
#RequestScoped
public class Resources {
#Produces
public FacesContext produceFacesContext() {
return FacesContext.getCurrentInstance();
}
}
Next you need to define an ArgumentCaptor which can catch the FacesMessage for your JUnit-Test. I´ve created it as a clss member which will be initialized in the #before section and get the null value in #teardown.
private ArgumentCaptor<FacesMessage> facesMessageCaptor;
#Before
public void setUp() {facesMessageCaptor = ArgumentCaptor
.forClass(FacesMessage.class);
}
#After
public void tearDown() { facesMessageCaptor = null; }
Now you just need to add two #Mocks to your test-class
#Mock
Resources resourcesMock;
#Mock
FacesContext facesContextMock;
So you did it! Write the test like this:
Mockito.doReturn(facesContextMock).when(resourcesMock).produceFacesContext();
// Execute Method
cut.warning("SOME_DETAIL_TEXT");
// Verify interactions with the Resources and Faces and maybe others...
verify(resourcesMock).produceFacesContext();
verify(facesContextMock).addMessage(Mockito.anyString() ,
facesMessageCaptor.capture());
verifyNoMoreInteractions(...., resourcesMock, facesContextMock);
// write assert (i´ve used hamcrast-corematchers - more readable)
actualMessage = (FacesMessage) facesMessageCaptor.getValue();
assertThat(FacesMessage.SEVERITY_WARN, is(equalTo(actualMessage.getSeverity())));
assertThat(MY_TITLE, is(equalTo(actualMessage.getSummary())));
assertThat("DETAIL_TEXT", is(equalTo(actualMessage.getDetail())));

How to mock feign.Client.Default with Mockito

I'm writing a Dropwizard application and using Feign for building client calls to outside services. I have custom encoders and decoders I'm registering with the feign.Builder like so:
this.feignBuilder = Feign.builder()
.contract(new JAXRSContract()) // we want JAX-RS annotations
.encoder(new JacksonEncoder()) // same as what dropwizard is using
.decoder(new CustomDecoder())
.errorDecoder(new CustomErrorDecoder())
.requestInterceptor(new AuthKeyInterceptor(config.getInterceptor()));
I'm writing unit tests for the feign client calls so I can watch how the feign machinery deals with my encoder/decoder overrides and bubbles on exceptions. I'm not interested in writing integration tests with a fake server right now (this is the most common type of test i see people writing for this situation).
This should be straight forward. I want to mock the point at which feign makes the request and have it return my fake response. That means I should mock the call to feign.Client.Default.execute so it returns my fake response when it makes the request a this call site. An example of what that mock looks like:
String responseMessage = "{\"error\":\"bad\",\"desc\":\"blah\"}";
feign.Response feignResponse = FeignFakeResponseHelper.createFakeResponse(404,"Bad Request",responseMessage);
Client.Default mockFeignClient = mock(Client.Default.class);
try {
when(mockFeignClient.execute(any(feign.Request.class),any(Request.Options.class))).thenReturn(feignResponse);
} catch (IOException e) {
assertThat(true).isFalse(); // fail nicely
}
No luck. The Cleint.Default class isn't mocked when I reach the call site for the request in the code. What am I doing wrong?
As mentioned before, Mockito is not powerful enough.
I solved this with a manual mock.
It's easier than it sounds:
MyService.Java
public class MyService{
//My service stuff
private MyFeignClient myFeignClient;
#Inject //this will work only with constructor injection
public MyService(MyFeignClient myFeignClient){
this.MyFeignClient = myFeignClient
}
public void myMethod(){
myFeignClient.remoteMethod(); // We want to mock this method
}
}
MyFeignClient.Java
#FeignClient("target-service")
public interface MyFeignClient{
#RequestMapping(value = "/test" method = RequestMethod.GET)
public void remotemethod();
}
If you want to test the code above while mocking the feignclient, do this:
MyFeignClientMock.java
#Component
public class MyFeignClientMock implements MyFeignClient {
public void remoteMethod(){
System.out.println("Mocked remoteMethod() succesfuly");
}
}
MyServiceTest.java
#RunWith(SpringJUnit4ClassRunner.class)
public class MyServiceTest {
private MyService myService;
#Inject
private MyFeignClientMock myFeignClientMock;
#Before
public void setUp(){
this.myService = new MyService(myFeignClientMock); //inject the mock
}
//Do tests normally here...
}
It turns out Mockito is not powerful enough to do the thing I assumed it could do. The correct solution is to use PowerMockito to mock the constructor so Client.Default returns the mocked instance when it is instantiated in the class that holds that reference.
After a lot of compilation-error pain I got PowerMockito to compile and it seemed like it was going to work. Alas it failed to return my mock and the calls were still going through. I've tried PowerMockito in the past and never got around to using it because of the extra problems it caused. So I'm still of the opinion that it's not super easy to just plug and play.
It's a shame that trying to do something like this is so hard.

Junit test - com.liferay.portal.kernel.bean.BeanLocatorException: BeanLocator has not been set

public class CustomServiceImplTest extends TestCase{
ApplicationContext ac;
private BeanLocator mockBeanLocator;
#Test
public void testCreateCategory() throws Exception {
CustomService customService = (CustomService) ac.getBean("customService");
customService.CreateCategory();
}
#Before
public void setUp()
{
mockBeanLocator = Mockito.mock(BeanLocator.class);
PortalBeanLocatorUtil.setBeanLocator(mockBeanLocator);
CompanyLocalServiceUtil mockCompanyLocalService = Mockito.mock(CompanyLocalServiceUtil.class);
ac = CustomSpringUtils.loadApplicationContext(new String[] { ""/applicationContext-Services.xml" });
}
}
I am using basic JUnit 4 and created above test class extending TestCase.
The exception I am getting follows :
java.lang.NullPointerException at com.liferay.portal.service.CompanyLocalServiceUtil.getCompanyByWebId(CompanyLocalServiceUtil.java:498)
The following method customService.CreateCategory(); has calls to Lifery util methods such as CompanyLocalServiceUtil.getCompanyByWebId and etc.
Please anyone shed some light on this. I really appreciate any help.
Do I need to provide Liferay DS information in spring config file?? OR
Is there any way I could stub out the data ??
I am trying to test a ADD operation on one of the Liferay entity class -
MBCategoryLocalServiceUtil.addCategory(...)
You have to inject/mock CompanyLocalService class in CompanyLocalServiceUtil. The Liferay way of doing it is:
CompanyLocalService service = ..... // mock;
new CompanyLocalServiceUtil().setService(service);
The setService is an instance method but is assign value to static field. Don't ask me why it is implemented and designed in such way.

Categories