I am using JMock-2.6.0. I have a map containing the names of methods and their expected return values.
I want to invoke a method on a mock object created using JMock.
Earlier I was able to this using JMock 1 as it follows following syntax:
mockObj.stubs().method(mymap.getKey()).will(new ReturnStub(mymap.getValue()));
But I am not sure, if there is a way to achieve this using JMock-2.
JMock-2's documentation is insufficient.
I believe this is the documentation you've been looking for:
Match Objects or Methods
Although matchers are normally used to specify acceptable parameter values, they can also be used to specify acceptable objects
or methods in an expectation, using an API syntax similar to that of
jMock 1. To do so, use a matcher where you would normally refer to a
mock object directly in the invocation count clause. Then chain
clauses together to define the expected invocation.
Their example includes:
To allow invocations of any bean property getter on any mock object:
allowing (any(Object.class)).method("get.*").withNoArguments();
For example you can use the following allowing... portion in a loop to achieve a similar result.
An sample test:
Interface:
public interface ThingOneI {
public abstract String getData();
public abstract void setData(String data);
public abstract String getRequest();
public abstract void setRequest(String request);
}
Impl:
public class ThingOne implements ThingOneI {
private String data;
private String request;
public ThingOne() {
}
#Override
public String getData() {
return data;
}
#Override
public void setData(String data) {
this.data = data;
}
#Override
public String getRequest() {
return request;
}
#Override
public void setRequest(String request) {
this.request = request;
}
}
Junit test:
import org.jmock.Expectations;
import org.jmock.Mockery;
import org.junit.Before;
import org.junit.Test;
public class ThingOneTest {
Mockery context = new Mockery();
#Before
public void setUp() throws Exception {
}
#Test
public void test() {
ThingOneI thingOne = context.mock(ThingOneI.class);
Map<String, String> methMap = new HashMap<String, String>();
methMap.put("getData", "5");
context.checking(new Expectations() {{
for (Map.Entry<String, String> entry : methMap.entrySet())
allowing(any(ThingOneI.class))
.method(entry.getKey())
.with(any(String.class));
will(returnValue(entry.getValue()));
}
}});
System.out.println(thingOne.getData());
}
}
Related
I am trying to write some generic code and facing issue. Here is code
public abstract class AbstractService<D extends IDTO> {
public String ex(D dto) {
return null;
}
}
public class AService extends AbstractService<TestA> {
#Override
public String ex(TestA dto) {
return "a";
}
}
public class BService extends AbstractService<TestB> {
#Override
public String ex(TestB dto) {
return "b";
}
}
class TestA impements IDTO {
}
class TestB impements IDTO {
}
So as you can see, its really simple code, one AbstractService with bounded param that extends IDTO.
Two implementation of service AService and BService which uses their respective DTO.
Not there is another class that need to call ex() method on basis of runtime instance.
here I am facing the problem.
public class TestAll {
public void executeRequest(final IDTO dto){
// serviceMap contains list of all Services here A and B
serviceMap.get(type).ex(dto);
}
}
Problem on line build().
The method build(capture#5-of ? extends IDTO) in the type AbstractService is not applicable for the arguments (IDTO)
Could someone help to fix this issue?
I found the reason why it was giving me the error. It was my mistake as I was trying to build a map with the help of Spring and was using bounded approach.
It was my previous code.
#Autowired
public void setServicesList(List<AbstractService<IDTO>> abstractServices) {
serviceMap = abstractServices.stream().collect(Collectors.toMap(AbstractService::getType, Function.identity()));
}
and I had to remove the bounded approach and now it's working.
public void setServicesList(List<AbstractService> abstractServices) {
serviceMap = abstractServices.stream().collect(Collectors.toMap(AbstractService::getType, Function.identity()));
}
In case you know what type of service holds the Map, you could do following:
// define your service map
private final Map<String, AbstractService<? extends IDTO>> serviceMap = Map.of(
"a", new AService(),
"b", new BService());
// cast `AbstractServise` from the map into required type:
public void executeRequest(final TestA dto){
((AbstractService<TestA>)serviceMap.get("a")).ex(dto);
}
public void executeRequest(final TestB dto){
((AbstractService<TestB>)serviceMap.get("b")).ex(dto);
}
I'm trying to find a way to generate a POJO object from the constructor of a class tagged with the #RunWith(Parameterized.class) annotation. The POJO would be used to generate the Object[] used as inputs for the constructor. Does something like this already exist? If not how could I create it?
Example code:
#RunWith(Parameterized.class)
public class Foo {
#ParameterizedTestPOJO // Annotation that would generate POJO
public Foo(String inputString, Integer inputInteger) {
// Does something
}
#Test
public testSomething() {
// Tests something
}
#Parameterized.Parameters
public static Iterable<Object[]> generateParameters() {
List<Object[]> parameters = new ArrayList<>();
// Example of how generated POJO could be used
parameters.add(new FooParameterizedPojo("input", 1).getParameters());
return parameters;
}
}
// Generated POJO
public class FooParameterizedPojo {
private String inputString;
private Integer inputInteger;
public FooParameterizedPojo(String inputString, Integer inputInteger) {
this.inputString = inputString;
this.inputInteger = inputInteger;
}
public Object[] getParameters() {
return new Object[] {inputString, inputInteger};
}
}
Edit: Maybe I could use a custom Lombok annotation? Seems promising.
I have designed the following interface:
public interface applyBuisnessRule {
public String execute(String jobCode)throws Exception;
}
and there are classes implementing it:
public class AccelImpl implements applyBuisnessRule {
private static final String Success = null;
#Override
public String execute(String jobCode) throws Exception {
// TODO Auto-generated method stub
return Success;
}
}
the other one is:
public class CardvaletImpl implements applyBuisnessRule {
private static final String Success = null;
public String execute(String jobCode) throws Exception {
return Success;
}
}
Please advise how can i make the below interface and class as more generic means the input parameter will be of string type but the return will be of object type so please advise how can i make it more generic one and it should return the object type as below we can clearly see that it is a stratergy design pattern but there is no generics in code
what I have tried is shown below also please advise is it the correct approach
the interface
interface applyBuisnessRule<T> {
public T execute(String jobCode) throws Exception;
}
the class
class CardvaletImpl<T> implements applyBuisnessRule<T> {
private static final String Success = null;
public T execute(String jobCode) throws Exception {
T result = null;
// put your logic and populate result here. I believe you are not going to return Success every time as it String
return result;
}
}
code excecution
CardvaletImpl<String> cardvaletImpl = new CardvaletImpl<>();
String result = cardvaletImpl.execute("JOBCODE");
folks please advise can we further improve the solution or not
I have the following class
public class One {
private Map<String, String> nodes = new HashMap<String, String>();
public void addNode(String node, String nodefield){
this.nodes.put(node, nodefield);
}
}
I want to write a test class to test the addNode method and have the following:
#RunWith(MockitoJUnitRunner.class)
public class OneTest {
#InjectMocks
private One one = new One();
#Mock
Map<String, String> nodes;
#Test
public void testAddNode(){
one.addNode("mockNode", "mockNodeField");
Mockito.verify(nodes).put("mockNode","mockNodeField");
}
}
which works. But I was wondering if there is a way to do it without using #InjectMocks like the following
public class OneTest {
private One one;
#Test
public void testAddNode(){
Map<String, String> nodes = Mockito.mock(Map.class);
one = Mockito.injectmocks(One.class, nodes); // or whatever equivalent methods are
one.addNode("mockNode", "mockNodeField");
Mockito.verify(nodes).put("mockNode","mockNodeField");
}
}
How about change the class by injecting the map as a dependency? This makes it easier to test and gives you the added benefit of being able to use an implementation of the Map interface, for example:
public class One {
private Map<String, String> nodes;
public One(Map<String, String> nodes) {
this.nodes = nodes;
}
public void addNode(String node, String nodefield){
this.nodes.put(node, nodefield);
}
}
Then to test:
Map mockMap = Mockito.mock(Map.class);
One one = new One(mockMap);
one.addNode("mockNode", "mockNodeField");
Mockito.verify(mockMap).put("mockNode","mockNodeField");
Okay I figured it out by using PowerMockito instead of normal Mockito.
public class OneTest {
private One one;
#Test
public void testAddNode(){
HashMap nodes = PowerMockito.mock(HashMap.class);
PowerMockito.whenNew(HashMap.class).withNoArguments().thenReturn(nodes);
One one = new One();
one.addNode("mockNode", "mockNodeField");
Mockito.verify(nodes).put("mockNode","mockNodeField");
}
}
However, I don't really know what PowerMockito does that Mockito doesn't do to make it work though.
According to the Spring documentation, you can receive all GET parameters in a map like so:
#GetMapping
public final ReturnType getAll(#RequestParam MultiValueMap<String, String> allRequestParams) {
...
}
Is it possible (and how) to also accept a custom Java object instead (for which a custom Converter exists via subclassing GenericConverter) in such a way that the Converter gets the whole request map for construction of its DTO object?
#GetMapping
public final ReturnType getAll(#RequestParam CustomDTO customObj) {
[...]
}
[...]
#Component
public class CustomDTOConverter implements GenericConverter {
#Override
public Set<ConvertiblePair> getConvertibleTypes() {
// Allow MultiValueMap.class to CustomDTO.class
[...]
}
#Override
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
final MultiValueMap<String, String> requestMap = (MultiValueMap<String, String>) source;
// Construct CustomDTO from the requestMap
}
}
Trying the above snippet will fail, complaining that there is no parameter customObj present.
For convert get parameters to java object use method parameter without annotations. CustomDto must have setters.
#GetMapping
public final ReturnType getAll(CustomDTO customObj) {
...
}
class CustomDto {
int x;
String s;
public void setX(int x) {
this.x = x;
}
public void setS(String s) {
this.s = s;
}
}
Url example:http://example.com/test?x=123&s=abc