How can I stub/mock a void method which populates some objects that would be used later.
class RequestHelper{
public void populateOrderRequestBody(String product,String quantity,String profile, OrderType orderType){
orderType.setProduct(product);
orderType.setQuantity(Integer.parseInt(quantity));
orderType.setUser(profile.getUserId());
} }
class ServiceClient{
RequestHelper rh;
public void docall(Order order){
OrderType orderType = FACTORY.CreateOrderType;
rh.populateOrderRequestBody(order.getProduct(),order.getQuantity(),order.getProfile(),orderType);
/**
* some other code
**/
}
public setRequestHelper(RequestHelper rh){
this.rh=rh;
}
public RequestHelper getRequestHelper(){
return this.rh;
}}
Now I want to test ServiceClient class which call RequestHelper to populate orderType object. How to stub the method of RequestHelper class.
In this particular case if no verification will be done to rh filed you just need a plain Stub - just to ensure no NullPointerException is thrown when testing the docall method. Mock will also be sufficient however is more advanced object and using it here is pointless. When it comes to Spy it's used to verify invocations on a real (in terms of not being mocked) object. Have a look at the example below - runs smoothly just with Stub:
#Grab('org.spockframework:spock-core:1.0-groovy-2.4')
#Grab('cglib:cglib-nodep:3.1')
import spock.lang.*
class Test extends Specification {
def 'spec'() {
given:
def service = new ServiceClient()
service.rh = Mock(RequestHelper)
when:
service.doCall(new Order())
then:
noExceptionThrown()
}
}
class Order {
String product
String quantity
String profile
}
class OrderType { }
class FACTORY {
static OrderType CreateOrderType = new OrderType()
}
class RequestHelper {
public void populateOrderRequestBody(String product, String quantity, String profile, OrderType orderType) {
orderType.setProduct(product);
orderType.setQuantity(Integer.parseInt(quantity));
orderType.setUser(profile.getUserId());
}
}
class ServiceClient {
RequestHelper rh;
public void doCall(Order order) {
OrderType orderType = FACTORY.CreateOrderType;
rh.populateOrderRequestBody(order.getProduct(), order.getQuantity(), order.getProfile(), orderType);
}
public setRequestHelper(RequestHelper rh){
this.rh=rh;
}
public RequestHelper getRequestHelper(){
return this.rh;
}
}
Very similar to Opal's answer but using a mock order..
class Test extends Specification {
def 'spec'() {
given:
def service = new ServiceClient()
def order = Mock(Order)
order.getProduct() >> 'product1'
order.getProfile() >> 'profile1'
order.getQuantity() >> 3
service.rh = Mock(RequestHelper)
when:
service.doCall(order)
then:
noExceptionThrown()
1 * rh.populateOrderRequestBody('product1',3,'profile1',FACTORY.CreateOrderType)
}
}
Note that this only works if the CreateOrderType.equals() will return true
Related
I have an object in use throughout my codebase, UnsecureObject. This object is auto-generated with no getters/setters, and all member fields are public. So editing is done by doing something like the following:
unsecureObjInstance.firstName = "Jane";
This is not desirable for numerous reasons that I probably don't have to explain here. But using this generated class is required for some other technical details with our messaging pipeline that I won't go into.
I have a desire is to leverage a mapping utility written by someone else on my team to convert this UnsecureObject to a pojo that I am writing.
An example of the mapper in action (with two normal classes w/ getters/setters) would be something like:
new MapperBuilder<>(PojoOne.class, PojoTwo.class)
.from(PojoOne::getName).to(PojoTwo::getFirstName)
.build();
This will map the PojoOne#name field to the PojoTwo#firstName field.
Is there a way to translate this to input my UnsecureObject here? I have tried something like the following:
new MapperBuilder<>(UnsecureObject.class, SecureObject.class)
.from(u -> u.firstName).to(SecureObject::getFirstName)
.build();
But get an error here, something along the lines of 'u -> u.firstName' could not be invoked.
So the question is:
Is there a way to essentially "construct" a getter on the fly using these public members? So in the .from() method, I can construct the call to look like a standard method that will yield my u.firstName?
Thanks for the help!
EDIT:
this is approx what the MapperBuilder class looks like (attempted to edit a bit to take away project specific wrappers/simplify)
/**
* This class is used to convert between POJO getter method references to the corresponding field names.
* #param <B> type
*/
public interface PojoProxy<B> {
/**
* Invokes the given getter method and returns information about the invocation.
* #param getter the getter to invoke
* #return information about the method invoked
*/
<T> GetterInvocation<T> invokeGetter(Function<B, T> getter);
}
/**
* Stores information about a method invocation.
* #param <T> method return type
*/
public interface GetterInvocation<T> {
public Class<T> getReturnType();
public String getFieldName();
}
/**
* A builder class to create {#link Mapper} instances.
* #param <FROM> source type
* #param <TO> target type
*/
public class MapperBuilder<FROM, TO> {
private final Class<FROM> _fromClass;
private final Class<TO> _toClass;
private final PojoProxy<FROM> _fromProxy;
private final PojoProxy<TO> _toProxy;
public MapperBuilder(Class<FROM> fromClass, Class<TO> toClass) {
_fromClass = fromClass;
_toClass = toClass;
//We will pretend there is an impl that provides the proxy.
//Proxies wrap the from and to classes in order to get reflection information about their getter calls.
_fromProxy = PojoProxy.of(fromClass);
_toProxy = PojoProxy.of(toClass);
}
public <FROM_VALUE> ToFieldBuilder<FROM_VALUE> from(Function<FROM, FROM_VALUE> getter) {
GetterInvocation<FROM_VALUE> methodInvocation = _fromProxy.invokeGetter(getter);
return new ToFieldBuilder<>(methodInvocation.getFieldName(), methodInvocation.getReturnType());
}
public class ToFieldBuilder<FROM_VALUE> {
private final String _fromFieldPath;
private final Class<FROM_VALUE> _fromClass;
public ToFieldBuilder(String fromFieldPath, Class<FROM_VALUE> fromClass) {
_fromFieldPath = fromFieldPath;
_fromClass = fromClass;
}
public <TO_VALUE> FromFieldBuilder<FROM_VALUE, TO_VALUE> to(Function<TO, TO_VALUE> getter) {
//similar to above, but now using a FromFieldBuilder.
}
}
public class FromFieldBuilder<FROM_VALUE, TO_VALUE> {
//impl..
}
}
I dont see MapperBuilder.from() method details, you can try this implementation of MapperBuilder.java Function (getter) -> (BiConsumer) setter
public class MapperBuilder<S, D> {
private final S src;
private final D dest;
public MapperBuilder(S src, Class<D> dest) {
this.src = src;
try {
this.dest = dest.newInstance();
} catch (Exception e) {
throw new RuntimeException("Required default constructor for: " + dest);
}
}
//getter - function to get value from source instance
//setter - biConsumer to set value to destination instance
//example - map(SrcClass::getSrcValue, DestClass::setDestValue)
public <V> MapperBuilder<S, D> map(Function<S, V> getter, BiConsumer<D, V> setter) {
setter.accept(dest, getter.apply(src));
return this;
}
public D build() {
return dest;
}
}
SrcClass.java some source class:
public class SrcClass {
private String srcValue;
public String getSrcValue() {
return srcValue;
}
public void setSrcValue(String srcValue) {
this.srcValue = srcValue;
}
}
DestClass.java some destination class:
package com.example.demo;
public class DestClass {
private String destValue;
public String getDestValue() {
return destValue;
}
public void setDestValue(String destValue) {
this.destValue = destValue;
}
}
DemoApplication.java demo:
public class DemoApplication {
public static void main(String[] args) {
SrcClass src = new SrcClass();
src.setSrcValue("someValue");
DestClass dest = new MapperBuilder<>(src, DestClass.class)
.map(SrcClass::getSrcValue, DestClass::setDestValue)
// map another fields
.build();
// for your UnsecureObject case
UnsecureObject unsecureObject = new MapperBuilder<>(src, UnsecureObject.class)
.map(SrcClass::getSrcValue,
(unsecure, srcValue) -> unsecure.unsecureValue = srcValue)
.build();
}
}
class SomeService{
public String getValue(){
return SomeUtil.generateValue();
}
}
class SomeUtil{
public static String generateValue() {
return "yahoo";
}
}
I want to unit test the SomeService.getValue method.
I am trying the following:
#Test
void "getValue should return whatever util gives"(){
def mockSomeUtil = mock(SomeUtil)
mockSomeUtil.static.generateValue().returns("blah")
play {
Assert.assertEquals(someService.getValue(), "blah")
}
}
But it fails as the util method isn't actually getting mocked.
Question:
How can I unit test my service method?
I made a quick test and it is working without a hassle:
#Grapes([
#Grab(group='org.gmock', module='gmock', version='0.8.3'),
#Grab(group='junit', module='junit', version='4.12')
])
import org.gmock.*
import org.junit.*
import org.junit.runner.*
class SomeService {
public String getValue(){
return SomeUtil.generateValue()
}
}
class SomeUtil {
public static String generateValue() {
return "yahoo"
}
}
#WithGMock
class DemoTest {
def someService = new SomeService()
#Test
void "getValue should return whatever util gives"() {
def mockSomeUtil = mock(SomeUtil)
mockSomeUtil.static.generateValue().returns("blah")
play {
Assert.assertEquals(someService.getValue(), "blah")
}
}
}
def result = JUnitCore.runClasses(DemoTest.class)
assert result.failures.size() == 0
If you need to invoke the service several times, you may need a stub, i.e.:
mockSomeUtil.static.generateValue().returns("blah").stub()
I want to use Guice and GuiceBerry to inject a non-static legacy service into a factory class. I then want to inject that factory into my Parameterized JUnit test.
However, the issue is JUnit requires that the #Parameters method be static.
Example factory:
#Singleton
public class Ratings {
#Inject
private RatingService ratingService;
public Rating classicRating() {
return ratingService.getRatingById(1002)
}
// More rating factory methods
}
Example test usage:
#RunWith(Parameterized.class)
public class StaticInjectParamsTest {
#Rule
public GuiceBerryRule guiceBerryRule = new GuiceBerryRule(ExtendedTestMod.class)
#Inject
private static Ratings ratings;
#Parameter
public Rating rating;
#Parameters
public static Collection<Rating[]> ratingsParameters() {
return Arrays.asList(new Rating[][]{
{ratings.classicRating()}
// All the other ratings
});
}
#Test
public void shouldWork() {
//Use the rating in a test
}
}
I've tried requesting static injection for the factory method but the Parameters method gets called before the GuiceBerry #Rule. I've also considered using just the rating's Id as the parameters but I want to find a reusable solution. Maybe my approach is flawed?
Unfortunately, JUnit needs to be able to enumerate all of the tests before running any tests, so the parameters method must be called before rules.
You could define an enum for the type of rating:
#RunWith(Parameterized.class)
public class StaticInjectParamsTest {
#Rule
public GuiceBerryRule guiceBerryRule
= new GuiceBerryRule(ExtendedTestMod.class);
#Inject
private Ratings ratings;
#Parameter
public RatingType ratingType;
#Parameters
public static Collection<RatingType> types() {
return Arrays.asList(RatingType.values());
}
#Test
public void shouldWork() {
Rating rating = ratings.get(ratingType);
// Use the rating in a test
}
}
Edit: Code for enum:
public enum RatingType {
CLASSIC(1002),
COMPLEX(1020);
private final int ratingId;
private RatingType(int ratingId) {
this.ratingId = ratingId;
}
// option 1: keep rating ID private by having a method like this
public get(RatingService ratingService) {
return ratingService.getRatingById(ratingId);
}
// option 2: have a package-scope accessor
int getRatingId() {
return ratingId;
}
}
Edit: if you go with option 2 you would then add a new method to get a Rating from a RatingType which would delegate to the service passing ratingId:
#Singleton
public class Ratings {
#Inject
private RatingService ratingService;
public Rating getRating(RatingType ratingType) {
return ratingService.getRatingById(
ratingType.getRatingId());
}
// More rating factory methods
}
If you don't want RatingType to be in your public API, you can define it in your test, and have a method in the enum named getRating()
public enum RatingType {
CLASSIC {
#Override public Rating getRating(Ratings ratings) {
return ratings.getClassicRating();
}
},
COMPLEX {
#Override public Rating getRating(Ratings ratings) {
return ratings.getComplexRating();
}
};
public abstract Rating getRating(Ratings ratings);
}
You could also create a value type instead of an enum.
This assumes you can write tests that should pass for all Rating instances.
If you have some common tests but some rating-specific tests, I would make an abstract base class that contains common tests, and an abstract createRating() method, and subclass it for every rating type.
My solution was to add a RatingId class that wraps an integer and create a factory RatingIds that I could then return static and use as parameters. I overloaded the getRatingById method in my RatingService interface to accept the new RatingId type, and then inject the rating service into my test and use it directly.
Added factory:
public class RatingIds {
public static RatingId classic() {
return new RatingId(1002);
}
// Many more
}
Test:
#RunWith(Parameterized.class)
public class StaticInjectParamsTest {
#Rule
public GuiceBerryRule guiceBerryRule = new GuiceBerryRule(ExtendedTestMod.class)
#Inject
private RatingService ratingService
#Parameter
public RatingId ratingId;
#Parameters
public static Collection<RatingId[]> ratingsParameters() {
return Arrays.asList(new RatingId[][]{
{RatingIds.classic()}
// All the other ratings
});
}
#Test
public void shouldWork() {
Rating rating = ratingService.getRatingById(ratingId.getValue())
//Use the rating in a test
}
}
In cases as yours, where the total number of generated parameter sets is known in advance, but building the parameters itself requires some context (e.g. autowired service instance with Spring) you can go the functional approach (with junit5 & parameterized)
Obviously that does not work, if the createParameter function itself depends on such contex:-/
class MyTestClass {
// may be autowired, cannot be static but is required in parameter generation
SomeInstance instance;
private interface SomeParamBuilder { SomeParam build(SomeInstance i);}
private static Stream<Arguments> createParamterFactories() {
return Stream.of(
Arguments.of((SomeParamBuilder)(i)->
{
return new SomeParam(i);
})
);
}
// does not work, because SomeParam needs SomeInstance for construction
// which is not available in static context of createParameters.
//#ParameterizedTest(name = "[{index}] {0}")
//#MethodSource("createParameters")
//void myTest(SomeParam param) {
//}
#ParameterizedTest(name = "[{index}] {0}")
#MethodSource("createParamterFactories")
void myTest(SomeParamBuilder builder) {
SomeParam param = builder.build(instance);
// rest of your test code can use param.
}
}
maven dep:
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-params</artifactId>
<version>5.2.0</version>
<scope>test</scope>
</dependency>
I did not get guiceberry to run (ancient dependencies), but using JUnitParamters and plain guice, this is rather simple:
#RunWith(JUnitParamsRunner.class)
public class GuiceJunitParamsTest {
public static class SquareService {
public int calculate(int num) {
return num * num;
}
}
#Inject
private SquareService squareService;
#Before
public void setUp() {
Guice.createInjector().injectMembers(this);
}
#Test
#Parameters({ "1,1", "2,4", "5,25" })
public void calculateSquares(int num, int result) throws Exception {
assertThat(squareService.calculate(num), is(result));
}
}
If you check the JUnitParams website, you will find a lot of other ways to define the parameters list. It is really easy to do this with the injecte service.
I have the following db table:
id method_id
1 1
1 2
1 3
and 2 classes:
EmailController and Smscontroller
in my code, I need to iterate over the table and according to the method_id (1 or 2) to invoke the send method of either EmailController or Smscontroller.
What is the recommended design pattern for it?
EDITED
There could be 100 methods! I put only 3. This is why I do not prefer the if else.
As well, the object that I send to EmailController send method is different than the one that I send to SmsController send method.
In EmailController I need to send User object.
In SmsController I need to send Manager object
I can't think of a design pattern. But for ultimate flexibility you can have a design similar to this:
public interface Sendable /* or Sender, SendingManager, etc. */ {
public int getId();
public void send();
}
public class EmailController implements Sendable {
}
public class SmsController implements Sendable {
}
public class Sendables {
private Map<Integer, Sendable> sendables = new HashMap<Integer, Sendable>();
public void addSendable(Sendable s) {
this.sendables.put(s.getId(), s);
}
public void sendById(Integer id) {
this.sendables.get(id).send();
}
}
Then you can use it like this:
Sendables sendables = new Sendables();
sendables.add(new EmailController());
sendables.add(new SmsController());
sendables.add(new ChatController());
// etc.
Row row = table.getRow(...); // let's assume this gets a row from your table
sendables.send(row.getId());
Another solution could be to have an extra table like this:
TABLE: CLASS_NAMES
method_id class_name
1 "com.foo.SmsController"
2 "com.foo.EmailController"
And then pass class_name to Class.forName and let it instantiate the appropriate controller for you to use.
EDIT: A reflection-based version of the code as suggested by Luis. Note that for production use you should ensure that the passed parameters are valid (not null, etc.) and also handle exceptions with rigor.
TABLE: CLASS_NAMES
method_id class_name param_class_name
1 "com.foo.SmsController" "com.foo.Manager"
2 "com.foo.EmailController" "com.foo.User"
SendManager
public class SendManager {
private static final String SEND_METHOD_NAME = "send";
/* DAO for the CLASS_NAMES tables */
private ClassNameDAO classNameDao;
/**
* Gets the row corresponding to methodId, for example
* (1, "com.foo.SmsController", "com.foo.Manager") then using reflection
* instantiates an instance of SmsController and invokes its send method
* with <code>param</code> passed to it.
*/
public void send(int methodId, Object param) throws Exception {
ClassNameRow classNameRow = classNameDao.findByMethodId(methodId);
String senderParameterClassName = className.senderParameterClassName();
Class paramClass = Class.forName(senderParameterClassName);
if (!paramClass.isInstance(param)) {
throw new IllegalArgumentException("methodId and param are not compatible");
}
String senderClassName = classNameRow.getSenderClassName();
Class senderClass = Class.forName(senderClassName);
/* Your sender classes must be JavaBeans and have no-arg constructors */
Object sender = senderClass.newInstance();
Class paramClass = Class.forName(senderParameterClassName);
Method send = senderClass.getMethod(SEND_METHOD_NAME, paramClass);
send.invoke(sender, param);
}
}
Sample Usage
SendManager sendManager = new SendManager();
Manager m = ...;
sendManager.send(1, m);
User u = ...;
sendManager.send(2, u);
How about this:
abstract class Controller {
public static Controller getInstance(int methodId) {
switch (methodId) {
case 1:
return new EmailController();
case 2:
return new SmsController();
default:
return null;
}
}
public abstract void send();
}
class EmailController extends Controller {
#Override
public void send() {
System.out.println("sending email");
}
}
class SmsController extends Controller {
#Override
public void send() {
System.out.println("sending sms");
}
}
And use it like this:
Controller.getInstance(methodId).send();
I'm using the Strategy pattern and the Factory Method pattern in my solution.
Strategy Pattern
http://johnlindquist.com/2010/08/25/patterncraft-strategy-pattern/
http://en.wikipedia.org/wiki/Strategy_pattern
I am having an abstract factory class StudentValidatorFactory which is suppossed to create(based on a specified parameter) various StudentValidator class instances to which a validation map has to be injected (see the code bellow).
public class StudentValidatorFactory{
public static final int JUNIOR_STUDENT_TYPE = 1;
public static final int SENIOR_STUDENT_TYPE = 2;
public StudentValidator createStudentValidator(int studentType) throws StudentValidatorCreationException{
Map<String,ValidationBean> validationMap = readValiationMapFromPersistentOrCachedStorage(studentType);
switch (studentType){
case JUNIOR_STUDENT:
return new JuniorStudentValidator(validationMap);
case SENIOR_STUDENT:
return new SeniorStudentValidator(validationMap);
}
}
}
public interface StudentValidator{
void validate(Student student) throws StudentValidationException;
}
public class JuniorStudentValidator{
private Map<String, ValidationBean> validationMap;
public JuniorStudentValidator(Map<String,ValidationBean> validationMap){
this.validationMap = validationMap;
}
public void validate(Student student) throws StudentValidationException{
// make use of validation map for apply junior student related validations on the student
}
}
public class SeniorStudentValidator{
private Map<String, ValidationBean> validationMap;
public SeniorStudentValidator(Map<String,ValidationBean> validationMap){
this.validationMap = validationMap;
}
public void validate(Student student) throws StudentValidationException{
// make use of validation map for apply senior student related validations on the student
}
}
My question is about the StudentValidatorFactory.createStudentValidator(int studentType) method whether reading the validation map from a persistent storage (based on the student type) should be done within the create method ? Otherwise said, should the factory be aware/dependent about such implementation details?
I'd appreciate if there would be a solution to avoid the switch(studentType) statement when creating the student validator - an idea on top of my head is to have an internally managed map and perform the StudentValidator concrete class instantiation via reflection .
Advantages of using such a technique is that the validators are much easier to be tested (through dependency injection).
Extract the readValiationMapFromPersistentOrCachedStorage(studentType) in a separated service interface StudentValidatorService and inject an instance of the service in the StudentValidatorFactory using a property or constructor argument:
public interface StudentValidatorService {
Map<String,ValidationBean> getValidationMap(int studentType);
}
public class StudentValidatorFactory{
public static final int JUNIOR_STUDENT_TYPE = 1;
public static final int SENIOR_STUDENT_TYPE = 2;
public StudentValidatorFactory(StudentValidatorService studentValidatorService) {
this.studentValidatorService = studentValidatorService;
}
public StudentValidator createStudentValidator(int studentType) throws StudentValidatorCreationException{
Map<String,ValidationBean> validationMap = studentValidatorService.getValidationMap(studentType);
switch (studentType){
case JUNIOR_STUDENT:
return new JuniorStudentValidator(validationMap);
case SENIOR_STUDENT:
return new SeniorStudentValidator(validationMap);
}
}
}
Now you can write an implementation of StudentValidatorService backed by database. Or you can write a mock implementation for testing. The implementation is now decoupled from the usage.
To remove the switch-case, invert it using an enum:
public enum StudentType {
JUNIOR_STUDENT {
public StudentValidator getValidator(Map<String,ValidationBean> validationMap) {
return new JuniorStudentValidator(validationMap);
}
},
SENIOR_STUDENT {
public StudentValidator getValidator(Map<String,ValidationBean> validationMap) {
return new SeniorStudentValidator(validationMap);
}
};
public abstract StudentValidator getValidator(Map<String,ValidationBean> validationMap);
}
public class StudentValidatorFactory{
public StudentValidatorFactory(StudentValidatorService studentValidatorService) {
this.studentValidatorService = studentValidatorService;
}
public StudentValidator createStudentValidator(StudentType studentType) throws StudentValidatorCreationException{
Map<String,ValidationBean> validationMap = studentValidatorService.getValidationMap(studentType);
return studentType.getValidator(validationMap);
}
}