How should I test this method using Mockito and Junit? - java

Suppose that there are classes like:
CivilAddSystem class :
class CivilAddSystem{
List<People> people = new ArrayList<>();
List<Town> towns = new ArrayList<>();
public People addPeople(People people) {
people.add(people);
return people;
}
public Town addTown(Town town) {
towns.add(town);
return town;
}
public House addHouse (House house, String townName) throws IllegalStateException {
Town town = getTown(townName);
if (null == town) throw new IllegalStateException("No matching town");
town.addHouse(house);
return house;
}
public List<String> getTown(String name) {
for (Town town : towns) {
if (town.getName().equals(name)) return town;
}
return null;
}
}
Town class:
public class Town {
List<House> houses = new ArrayList<>();
String name;
String abbreviation;
public Town (String name, String abbreviation) {
this.name = name;
this.abbreviation = abbreviation;
}
public String getName() {
return name;
}
public String getAbbreviation() {
return abbreviation;
}
public void addHouse(House house) {
houses.add(house);
}
public House getHouse(String unitNumber) {
for (House house : houses) {
if (house.getUnitNumber().equals(unitNumber)) return house;
}
return null;
}
}
House class:
public class House {
private final List<People> people = new ArrayList<>();
private final String unitNumber;
private final String houseName;
public House (String unitNumber, String houseName) {
this.unitNumber= unitNumber;
this.houseName= houseName;
}
public String getUnitNumber() {
return unitNumber;
}
public String getHouseName() {
return houseName;
}
private People checkMovedInPeople(People person) {
if (null == person) throw new NullPointerException();
for (People movedIn : people) {
if (movedIn.getName().equals(person.getName())) return movedIn;
if (movedIn.getPersonID().equals(person.getPersonID())) return movedIn;
}
return null;
}
public void moveInPeople(People person) throws IllegalArgumentException, IllegalStateException {
if (null == person) throw new IllegalArgumentException("Person shouldn't be null");
if (null != checkMovedInPeople(person)) throw new IllegalStateException("Person is already in the house");
people.add(person);
}
public List<String> getPeople() {
List<String> results = new ArrayList<>();
for (People person: people) {
results.add(person.getPersonID());
}
return results;
}
public People getPerson(String match) {
for (People person: people) {
if (person.getPersonID().equals(match)) return person;
if (person.getName().equals(match)) return person;
}
return null;
}
}
And for the people class, it just has two variables: String PersonID and String Name and their getter methods.
So, what I want to achieve is that, I am currently trying to test the addPeople method in CivilAddSystem class and I want to test it independently using mockito.
The test case I wrote using JUnit is like this:
#Test
public void testAddPeople() {
CivilAddSystem CAS = new CivilAddSystem();
Town town = CAS.addTown("BlueTown", "BT");
House house = CAS.addHouse("U180", "BlueHouse", "BlueTown");
People bob = CAS.addPeople("1", "Bob");
Assert.assertEquals(CAS.getTown("BlueTown").getHouse("U180").getPerson("1"), null);
house.moveInPeople(bob);
Assert.assertEquals(CAS.getTown("BlueTown").getHouse("U180").getPerson("1").getPersonID, 1);
}
But I am really struggling with applying mockito for this test case.
What I did so far is just mocking Town, House and People classes, (not the CivilAddSystem class since it is the one that is being tested), and stopped there...
Can anyone gives me a hint on how to apply mockito for that above test case?
p.s) A little bit of modification for the codes above is accepted (for example, applying dependency injection and something like this are accepted).
Thanks in advance!

Mocking gives you the ability to have a class look like another class or a class matching an interface. So if you wanted to test Town, you don't want to go through creating Houses, you just use Mockito to mock the house.
Ideally, Dwelling would be an interface, and there would be House, TownHome, Condo, RanchHouse, etc. as implementations. Then, when you are testing the CivilAddSystem, you aren't testing any of the TownHome implementation code. You have isolated it so that you are just testing the one class.
So you could create something like this:
// unit tests should only test one piece of functionality at a time.
// This should only test the addition of a Person. You should expect
// to have lots of unit tests so that when one breaks, you can tell
// exactly what broke
#Test
public void testAddTown() {
Town mockedTown = Mockito.mock(Town.class);
CivilAddSystem CAS = new CivilAddSystem();
Town town = CAS.addTown(mockedTown);
// verify that the town that was put in is the same as you get out...
// note that you should not be testing the functionality of Town here
// if you do, this breaks the isolation
Assert.assertTrue(CAS.getTowns().contains(mockedTown));
}
For advanced functionality, you can stub functionality. For example, if you needed to test if it was a large city, and CAS
// checks this by determining if the population is > 100000
#Test
public void testAddTown() {
Town mockedTown = Mockito.mock(Town.class);
when(mockedTown.getPopulation()).thenReturn(100001)
CivilAddSystem CAS = new CivilAddSystem();
// verify that the current state is the expected state
Assert.assertEquals(CAS.getNumberOfLargeTowns(), 0);
// make a change
Town town = CAS.addTown(mockedTown);
// test that the updates state is as expected
Assert.assertEquals(CAS.getNumberOfLargeTowns(), 1);
}

Related

What am I doing wrong with my For loop in java?

I have been looking around for some answers to this question and I just can't seem to figure it out. I think that the issue seems to be with the 'scope' of my code but I don't know what I'm doing wrong and I could really use some help. I'm very new to Java.
My goal
Test to see if an object already exists in an array before adding it.
If the object already exists in the array, return null.
If it doesn't exist in the array, create it and then return it.
The Code
public Business addBusiness(String person, String business, String location) {
int id = 0;
for (Business business : businesses ) {
if (business.getPerson().equals(person)) {
if (business.getBusiness().equals(business)) {
if (business.getLocation().equals(location)) {
return null;
}
}
}
}
Business newBusiness = new Business(person, business, location, id);
return newBusiness;
}
What happens when I run it
When I run the code it will just happily create object after object with the same details. This leads me to believe that there is a problem with my logic. I was expecting that when it returned null, that would be the end of it.
I would appreciate any tips you can give me on solving this problem.
EDIT: The 'Business' class
public class Business {
// Attributes //
private String person, business, location;
private int id;
// Constructor //
public Business(String person, String business, String location, int id) {
this.person = person;
this.business = business;
this.location = location;
this.id = id;
}
// Getters //
public String getPerson() {
return person;
}
public String getBusiness() {
return business;
}
public String getLocation() {
return location;
}
public int getId() {
return id;
}
}
Try
public Business addBusiness(String person, String business, String location)
{
int id = 0;
for (Business b : businesses ) {
if (b.getPerson().equals(person)) {
if (b.getBusiness().equals(business)) {
if (b.getLocation().equals(location)) {
return null;
}
}
}
}
Business newBusiness = new Business(person, business, location, id);
return newBusiness;
}
You were masking the parameter business from the function's signature with the object you're iterating over in the loop. Renaming this to b avoids the issue.
Okay -- so I think that I figured it out. Thank you so much to everyone for your help on this matter.
public Business addBusiness(String person, String business, String location)
{
int id = 0;
for (Business business : businesses ) {
if (business.getPerson().equals(person)) {
if (business.getBusiness().equals(business)) {
if (business.getLocation().equals(location)) {
return null;
}
}
}
}
Business newBusiness = new Business(person, business, location, id);
return newBusiness;
}
The issue was caused because I never actually added my newBusiness object into the array once it was created. So every time it ran it would never match an existing entry because there were no entries in the array.
The correct code should be something like:
public Business addBusiness(String person, String business, String location)
{
int id = 0;
for (Business b : businesses ) {
if (b.getPerson().equals(person)) {
if (b.getBusiness().equals(business)) {
if (b.getLocation().equals(location)) {
return null;
}
}
}
}
Business newBusiness = new Business(person, business, location, id);
b.add(newBusiness); // This was the missing line, now it seems to work fine.
return newBusiness;
}
Clearly, I still have a lot to learn.

Builder Design Pattern with sub-classing and required parameters?

Recently I came into a situation where the builder pattern was very strong, but I had the need to subclass. I looked up some solutions and some suggested generics while others suggested normal subclassing. However, none of the examples I looked at had required fields in order to even begin building an object. I wrote a tiny example to illustrate where I'm getting stuck. At every turn I kept running into a wall of problems where things would return the wrong class, can't override static methods, returning super() returns the wrong data type, etc. I have a feeling there is no way out except excessive use of generics.
What is the correct way to go in this situation?
Tester
import person.Person;
import person.Student;
public class Tester
{
public static void main(String[] args)
{
Person p = Person.builder("Jake", 18).interest("Soccer").build();
// Student s = Student.builder(name, age) <-- It's weird that we still have access to pointless static method
// Student s = Student.builder("Johnny", 24, "Harvard", 3).address("199 Harvard Lane") <-- returns Person builder, not student
Student s = ((Student.Builder)Student.builder("Jack", 19, "NYU", 1).address("Dormitory")).build(); // really bad
}
}
Person Class
package person;
import java.util.ArrayList;
import java.util.List;
public class Person
{
// Required
protected String name;
protected int age;
// Optional
protected List<String> interests = new ArrayList<>();
protected String address = "";
protected Person(String name, int age)
{
this.name = name;
this.age = age;
}
public String getName() { return name; }
public int getAge() { return age; }
public List<String> getInterests() { return interests; }
public String getAddress() { return address; }
// person.person does not allow builder construction
// unless all required fields are provided
/* Problem: I have to repeat the constructor fields here, very annoying */
public static Builder builder(String name, int age)
{
Person p = new Person(name, age);
return new Builder(p);
}
public static class Builder
{
Person reference;
protected Builder(Person reference)
{
this.reference = reference;
}
public Builder address(String address)
{
reference.address = address;
return this;
}
public Builder interest(String interest)
{
reference.interests.add(interest);
return this;
}
public Person build()
{
return reference;
}
}
}
Student Class
package person;
import java.util.ArrayList;
import java.util.List;
public class Student extends Person
{
// Required
protected String school;
protected int year;
// Optional
protected List<String> subjects = new ArrayList<>();
// This looks good
public Student(final String name, final int age, final String school, final int year)
{
super(name, age);
this.school = school;
this.year = year;
}
public String getSchool() { return school; }
public int getYear() { return year; }
public List<String> getSubjects() { return subjects; }
/* Here's where my issues are:
* Override doesn't compile on static methods but how else can I describe that I want to
* override this functionality from the Person class?
*
* Extending 'Person' does not enforce that I need to provide 'name', 'age', etc like it would
* if this was a normal design pattern using the 'new' keyword. I have to manually drag fields
* from 'person' and place them here. This would get VERY messy with an additional class
*
* User can STILL call the Person builder on a Student object, which makes no sense. */
/*#Override*/ public static Builder builder(String name, int age, String school, int year)
{
Student s = new Student(name, age, school, year);
return new Builder(s);
}
public static class Builder extends Person.Builder
{
// Student reference; <--- this should not be needed since we already
// have a variable for this purpose from 'Person.Builder'
public Builder(final Student reference)
{
super(reference);
}
/* Things begins to get very messy here */
public Builder subject(String subject)
{
((Student)reference).subjects.add(subject);
// I guess I could replace the reference with a student one, but
// I feel like that infringes on calling super() builder since we do the work twice.
return this;
}
#Override public Student build()
{
// I can either cast here or
// rewrite 'return reference' every time.
// Seems to infringe a bit on subclassing.
return (Student)super.build();
}
}
}
What you write here :
Student s = ((Student.Builder)Student.builder("Jack", 19, "NYU", 1).address("Dormitory")).build(); // really bad
is indeed not very natural and you should not need to cast.
We expect rather something like :
Student s = Student.builder("Jack", 19, "NYU", 1).address("Dormitory")).build();
Besides all casts you did in the implementation of Student.Builder are also noise and statements that may fail at runtime :
/* Things begins to get very messy here */
public Builder subject(String subject) {
((Student)reference).subjects.add(subject);
return this;
}
#Override public Student build() {
return (Student)super.build();
}
Your main issue is the coupling between the Builder classes and the building methods.
A important thing to consider is that at compile time, the method binding (method selected by the compiler) is performed according to the declared type of the target of the invocation and the declared type of its arguments.
The instantiated type is considered only at runtime as the dynamic binding is applied: invoking the method bounded at compile time on the runtime object.
So this overriding defined in Student.Builder is not enough :
#Override public Student build() {
return (Student)super.build();
}
As you invoke :
Student.builder("Jack", 19, "NYU", 1).address("Dormitory").build();
At compile time, address("Dormitory") returns a variable typed as Person.Builder as the method is defined in Person.Builder :
public Builder address(String address){
reference.address = address;
return this;
}
and it not overriden in Student.Builder.
And at compile time, invoking build() on a variable declared as Person.Builder returns a object with as declared type a Person as the method is declared in Person.Builder as :
public Person build(){
return reference;
}
Of course at runtime, the returned object will be a Student as
Student.builder("Jack", 19, "NYU", 1) creates under the hood a Student and not a Person.
To avoid cast to Student.builder both from the implementation and the client side, favor composition over inheritancy :
public static class Builder {
Person.Builder personBuilder;
private Student reference;
public Builder(final Student reference) {
this.reference = reference;
personBuilder = new Person.Builder(reference);
}
public Builder subject(String subject) {
reference.subjects.add(subject);
return this;
}
// delegation to Person.Builder but return Student.Builder
public Builder interest(String interest) {
personBuilder.interest(interest);
return this;
}
// delegation to Person.Builder but return Student.Builder
public Builder address(String address) {
personBuilder.address(address);
return this;
}
public Student build() {
return (Student) personBuilder.build();
}
}
You can now write :
Student s = Student.builder("Jack", 19, "NYU", 1)
.address("Dormitory")
.build();
or even that :
Student s2 = Student.builder("Jack", 19, "NYU", 1)
.interest("Dance")
.address("Dormitory")
.build();
Composition introduces generally more code as inheritancy but it makes the code
both more robust and adaptable.
As a side note, your actual issue is enough close to another question I answered 1 month ago.
The question and its answers may interest you.
A few thoughts as background
Static methods are not so great,
they make unit testing more difficult.
It is fine to put the builder as a static, nested class, but if you are using a builder to construct a class you should make the constructor not-public.
I prefer to have the builder be a separate class in the same package and to make the constructor (of the class that is created by the builder) package access.
Limit the builder constructor parameters.
I'm not a fan of using a class hierarchy for builders.
The Person and Student classes each have a builder.
Some Code
public class PersonBuilder
{
private String address;
private int age;
private final List<String> interestList;
private String name;
public PersonBuilder()
{
interestList = new LinkedList<>();
}
public void addInterest(
final String newValue)
{
// StringUtils is an apache utility.
if (StringUtils.isNotBlank(newValue))
{
interestList.add(newValue);
}
return this;
}
public Person build()
{
// perform validation here.
// check for required values: age and name.
// send all parameters in the constructor. it's not public, so that is fine.
return new Person(address, age, interestList, name);
}
public PersonBuilder setAddress(
final String newValue)
{
address = newValue;
return this;
}
public PersonBuilder setAge(
final int newValue)
{
age = newValue;
return this;
}
public PersonBuilder setInterestList(
final List<String> newValue)
{
interestList.clear();
if (CollectionUtils.isNotEmpty(newValue))
{
interestList.addAll(newValue);
}
return this;
}
public PersonBuilder setName(
final String newValue)
{
name = newValue;
return this;
}
}
public class Person
{
private Person()
{
}
Person(
final String addressValue,
final int ageValue,
final List<String> interestListValue,
final String name)
{
// set stuff.
// handle null for optional parameters.
}
// create gets or the fields, but do not create sets. Only the builder can set values in the class.
}

Should be localization part of domain in DDD

While following DDD concept I'm struggling on decision if I should make my domain localization aware? I came with two two solutions how to solve this. Both makes domain localization aware in different places. Should I even place localized text to domain? Share your solution for this problem or pros and cons of my two examples. Thanks.
Example 1
class Persion {
String name;
// other fields ommited
void rename(String newName) {
String oldName = this.name;
this.name = newName
// publish event with old name and new name
}
String name() {
return name;
}
}
class PersionRepository {
void store(Persion persion) {
Locale loc = LocaleContextHolder.get().getLocale();
// store object to DAO - create/update fields for context locale
}
// other methods ommited
}
Example 2
class Persion {
Map<Locale, String> name;
// other fields ommited
void rename(String newName) {
Locale locale = LocaleContextHolder.get().getLocale();
String oldName = this.name.put(locale, newName);
// publish event with old name and new name
}
String name() {
Locale locale = LocaleContextHolder.get().getLocale();
return this.name.get(locale);
}
}
class PersionRepository {
void store(Persion persion) {
// store object to DAO - create/update fields for all locales
}
// other methods ommited
}
In most of cases, the best option is to remove localization from the domain.
Domain classes should only contain data that are relevant to their invariants, since they are responsible for business rules. To retrieve localized descriptions, use projective DTOs and applicative services.
You could use something like this:
public final class VatCode {
private final String _code;
public VatCode(String code)
{
// VAT code validation here...
_code = code;
}
#Override
public String toString() {
return _code;
}
#Override
public boolean equals(Object obj) {
// ...
}
#Override
public int hashCode() {
// ...
}
}
public class Person {
private final VatCode _identifier;
public Person(VatCode identifier)
{
_identifier = identifier;
}
// some command and some query here...
}
public class PersonDTO {
private final String _vatCode;
private final String _personalDescription;
public PersonDTO(String _vatCode, String _personalDescription) {
this._vatCode = _vatCode;
this._personalDescription = _personalDescription;
}
// other fields here...
public String getVatCode()
{
return _vatCode;
}
public String getPersonalDescription()
{
return _personalDescription;
}
// some more getter here
}
public interface LocalizedPersonalInformationService {
PersonDTO getInformationOf(VatCode person, Locale localization) throws ProperExceptionList;
}
That is:
something like a VatCode valueobject (that overrides equals, hashCode and toString) to identify the Person entity
a Person entity, holding the minimum amount of data required to ensure business invariants and exposing a set of command and queries
a PersonDTO that carries useful descriptions (some call this a read-model)
a LocalizedPersonalInformationService that is able to provide PersonDTOs.
and (obviously) all the needed exceptions... :-)
If at all possible put all your localization in the UI layer. Sometimes people find that difficult to do. For example, I worked on a project where the business logic would throw an exception and that exception would get displayed in the UI. To localize the exception we had to do something like the following (details omitted for brevity, also we had to have a LocalizedRuntimeException and a LocalizedException):
//====ArbitraryBusinessLogic.java====
if(badThing) {
throw new SubclassOfLocalizedException(LocalizedStrings.ERROR_FOO,param1,param2);
}
//====LocalizedException.java====
public class LocalizedException extends Exception {
private LocalizationKey localizationKey;
Object [] params;
public LocalizedException(LocalizationKey localizationKey, Object ... params) {
super();
localizationKey = localizationKey
params = params;
}
public String getLocalizedMessage(Locale locale) {
//message would be something like "The %s foo'd the %s"
//or of course "le %s foo'd le %s" (FYI: I don't speak French)
String message = getLocalizedMessageForKey(localizationKey);
return String.format(locale,message,params);
}
public String getLocalizedMessage() {
return getLocalizedMessage(getDefaultLocale());
}
public String getMessage() {
return getLocalizedMessage();
}
}

Capturing method parameter in jMock to pass to a stubbed implementation

I wish to achieve the following behavior.
My class under test has a dependency on some other class, I wish to mock this dependency with jMock. Most of the methods would return some standard values, but there is one method, where I wish to make a call to a stubbed implementation, I know I can call this method from the will(...) but I want the method to be called by the exact same parameters that were passed to the mocked method.
Test
#Test
public void MyTest(){
Mockery context = new Mockery() {
{
setImposteriser(ClassImposteriser.INSTANCE);
}
};
IDependency mockObject = context.mock(IDependency.class);
Expectations exp = new Expectations() {
{
allowing(mockObject).methodToInvoke(????);
will(stubMethodToBeInvokedInstead(????));
}
};
}
Interface
public interface IDependency {
public int methodToInvoke(int arg);
}
Method to be called instead
public int stubMethodToBeInvokedInstead(int arg){
return arg;
}
So how do I capture the parameter that were passed to the method being mocked, so I could pass them to the stubbed method instead?
EDIT
Just to give another example, let's say I wish to mock the INameSource dependency in the following (C#) code, to test the class Speaker
public class Speaker
{
private readonly string firstName;
private readonly string surname;
private INameSource nameSource ;
public Speaker(string firstName, string surname, INameSource nameSource)
{
this.firstName = firstName;
this.surname = surname;
this.nameSource = nameSource;
}
public string Introduce()
{
string name = nameSource.CreateName(firstName, surname);
return string.Format("Hi, my name is {0}", name);
}
}
public interface INameSource
{
string CreateName(string firstName, string surname);
}
This is how it can be done in Rhino Mocks for C# I understand it can't be as easy as this since delegates are missing in Java
The solution from Duncan works well, but there is even a simpler solution without resort to a custom matcher. Just use the Invocation argument that is passed to the CustomActions invoke method. At this argument you can call the getParameter(long i) method that gives you the value from the call.
So instead of this
return matcher.getLastValue();
use this
return (Integer) invocation.getParameter(0);
Now you don't need the StoringMatcher anymore: Duncans example looks now like this
#RunWith(JMock.class)
public class Example {
private Mockery context = new JUnit4Mockery();
#Test
public void Test() {
final IDependency mockObject = context.mock(IDependency.class);
context.checking(new Expectations() {
{
// No custom matcher required here
allowing(mockObject).methodToInvoke(with(any(Integer.class)));
// The action will return the first argument of the method invocation.
will(new CustomAction("returns first arg") {
#Override
public Object invoke(Invocation invocation) throws Throwable {
return (Integer) invocation.getParameter(0);
}
});
}
});
Integer test1 = 1;
Integer test2 = 1;
// Confirm the object passed to the mocked method is returned
Assert.assertEquals((Object) test1, mockObject.methodToInvoke(test1));
Assert.assertEquals((Object) test2, mockObject.methodToInvoke(test2));
}
public interface IDependency {
public int methodToInvoke(int arg);
}
Like Augusto, I'm not convinced this is a good idea in general. However, I couldn't resist having a little play. I created a custom matcher and a custom action which store and return the argument supplied.
Note: this is far from production-ready code; I just had some fun. Here's a self-contained unit test which proves the solution:
#RunWith(JMock.class)
public class Example {
private Mockery context = new JUnit4Mockery();
#Test
public void Test() {
final StoringMatcher matcher = new StoringMatcher();
final IDependency mockObject = context.mock(IDependency.class);
context.checking(new Expectations() {
{
// The matcher will accept any Integer and store it
allowing(mockObject).methodToInvoke(with(matcher));
// The action will pop the last object used and return it.
will(new CustomAction("returns previous arg") {
#Override
public Object invoke(Invocation invocation) throws Throwable {
return matcher.getLastValue();
}
});
}
});
Integer test1 = 1;
Integer test2 = 1;
// Confirm the object passed to the mocked method is returned
Assert.assertEquals((Object) test1, mockObject.methodToInvoke(test1));
Assert.assertEquals((Object) test2, mockObject.methodToInvoke(test2));
}
public interface IDependency {
public int methodToInvoke(int arg);
}
private static class StoringMatcher extends BaseMatcher<Integer> {
private final List<Integer> objects = new ArrayList<Integer>();
#Override
public boolean matches(Object item) {
if (item instanceof Integer) {
objects.add((Integer) item);
return true;
}
return false;
}
#Override
public void describeTo(Description description) {
description.appendText("any integer");
}
public Integer getLastValue() {
return objects.remove(0);
}
}
}
A Better Plan
Now that you've provided a concrete example, I can show you how to test this in Java without resorting to my JMock hackery above.
Firstly, some Java versions of what you posted:
public class Speaker {
private final String firstName;
private final String surname;
private final NameSource nameSource;
public Speaker(String firstName, String surname, NameSource nameSource) {
this.firstName = firstName;
this.surname = surname;
this.nameSource = nameSource;
}
public String introduce() {
String name = nameSource.createName(firstName, surname);
return String.format("Hi, my name is %s", name);
}
}
public interface NameSource {
String createName(String firstName, String surname);
}
public class Formal implements NameSource {
#Override
public String createName(String firstName, String surname) {
return String.format("%s %s", firstName, surname);
}
}
Then, a test which exercises all the useful features of the classes, without resorting to what you were originally asking for.
#RunWith(JMock.class)
public class ExampleTest {
private Mockery context = new JUnit4Mockery();
#Test
public void testFormalName() {
// I would separately test implementations of NameSource
Assert.assertEquals("Joe Bloggs", new Formal().createName("Joe", "Bloggs"));
}
#Test
public void testSpeaker() {
// I would then test only the important features of Speaker, namely
// that it passes the right values to the NameSource and uses the
// response correctly
final NameSource nameSource = context.mock(NameSource.class);
final String firstName = "Foo";
final String lastName = "Bar";
final String response = "Blah";
context.checking(new Expectations() {
{
// We expect one invocation with the correct params
oneOf(nameSource).createName(firstName, lastName);
// We don't care what it returns, we just need to know it
will(returnValue(response));
}
});
Assert.assertEquals(String.format("Hi, my name is %s", response),
new Speaker(firstName, lastName, nameSource).introduce());
}
}
JMock doesn't support your use case (or any other mocking framework I know of in java).
There's a little voice in my head that says that what you're trying to do is not ideal and that your unit test might be to complicated (maybe it's testing too much code/logic?). One of the problems I see, is that you don't know which values those mocks need to return and you're plugging something else, which might make each run irreproducible.

Can I use my objects without fully populating them?

I have situation. I have to create a Sports Club system in JAVA. There should be a class your for keeping track of club name, president name and braches the club has. For each sports branch also there should be a class for keeping track of a list of players. Also each player should have a name, number, position and salary.
So, I come up with this. Three seperate classes:
public class Team
{
String clubName;
String preName;
Branch []branches;
}
public class Branch
{
Player[] players;
}
public class Player
{
String name;
String pos;
int salary;
int number;
}
The problems are creating Branch[] in another class and same for the Player[]. Is there any simplier thing to do this? For example, I want to add info for only the club name, president name and branches of the club, in this situation, won't i have to enter players,names,salaries etc. since they are nested in each other. I hope i could be clear. For further questions you can ask.
Here's a more complete, formal example of your scenario using conventional Accessors/Mutators (getters/setters), constructors, and Lists. The main() method below illustrates how to use your classes.
public class SportsClub
{
public static void main(String[] args)
{
//Create a team without any branches
Team myTeam = new Team("Southpaws", "South");
//Create a new Branch without any players
Branch myBranch = new Branch();
//Add myBranch to myTeam
myTeam.getBranches().add(myBranch);
//Create a new player
Player myPlayer = new Player("Bob", "Center", 120, 3);
//Add myPlayer to myBranch (and therefore myTeam)
myBranch.getPlayers().add(player);
}
}
public class Team
{
private String clubName;
private String preName;
private List<Branch> branches;
public Team(String clubName, String preName)
{
this.clubName = clubName;
this.preName = preName;
branches = new ArrayList<Branch>();
}
public String getClubName() { return clubName; }
public String getPreName() { return preName; }
public List<Branch> getBranches() { return branches; }
public void setClubName(String clubName) { this.clubName = clubName; }
public void setPreName(String preName) { this.preName = preName; }
public void setBranches(List<Branch> branches) { this.branches = branches; }
}
public class Branch
{
private List<Player> players = new ArrayList<Player>();
public Branch() {}
public List<Player> getPlayers() { return players; }
public void setPlayers(List<Player> players) { this.players = players; }
}
public class Player
{
private String name;
private String pos;
private Integer salary;
private Integer number;
public Player(String name, String pos, Integer salary, Integer number)
{
this.name = name;
this.pos = pos;
this.salary = salary;
this.number = number;
}
public String getName() { return name; }
public String getPos() { return pos; }
public Integer getSalary() { return salary; }
public Integer getNumber() { return number; }
public void setName(String name) { this.name = name; }
public void setPos(String pos) { this.pos = pos; }
public void setSalary(Integer salary) { this.salary = salary; }
public void setNumber(Integer number) { this.number = number; }
}
To answer your question, yes, you can create these objects without populating the Lists with players. The SportsClub.main() above illustrates that.
I would use a List rather than an array since they're (easily) dynamically resizable, but otherwise, you're on the right track.
Think about encapsulation and visibility too. Make all those fields private and provide accessors.
You could create an empty Branch[] array (or better yet - a list) at initialization and add to it later, that way you don't have to enter all the information upon creation - same goes for Player[].
Something like:
public class Team
{
String clubName;
String preName;
private List<Branch> branches;
public Team (String club, String pre) {
clubName = club;
preName = pre;
branches = new LinkedList<Branch>();
}
public void addBranch (Branch branch) {..}
}
public class Branch
{
private List<Player> players;
public Branch () {
players = new LinkedList<Player>();
}
public void addPlayer (Player player) {..}
}
public class Player
{
String name;
String pos;
int salary;
int number;
}
I think that's good. You should probably have methods in the classes to manage your information though--don't try to do anything serious from "Outside" these classes.
to be more specific: All your members should be private and only used/accessed from within the classes--also in general avoid setters and getters, instead ask the class to do things for you.
For example, if you wanted to know how many players were in a branch, you would call branch.countPlayers, not access the Player array to count the players from outside.
If you wanted to know how many players were in a team, you would call team.countPlayers which would call branch.countPlayers for each Branch, sum them up and return the value.
If you wanted to see which branch a player was in, you would call Team.findPlayer(playerName). Team would call branch.hasPlayer(playerName) on each branch until it returned a true, then Team would return the Branch object that returned true.
etc.
Note that this resolves your "Populated or not" issue. If you simply have methods like "hasBranch()", "addBranch()", "removeBranch()" then it doesn't matter how or when you populate the branches array since you control it all within the Team class you can change it's implementation at any time and not change a single line outside that class.
You won't have to enter anything into the players array, nor the branch[]. Provided you make the fields accessible, of have properties, you will be able to put them in however you like.
The class structure looks good to me, but a List would be better so that you don't have to worry about resizing arrays down the road.
Nothing wrong with your classes. I personally would use a strongly-typed List to store the branches and players:
public class Team
{
String clubName;
String preName;
List<Branch> branches;
}
public class Branch
{
List<Player> players;
}
Not sure of the requirement, but you'd probably want to have some kind of identifier or name for each Branch, right?
There's nothing in these classes that forces you to create new players just to instantiate a Branch. The list of Players can remain null or empty until you need them.

Categories

Resources