JUnit: Add two duplicated fixtures to some method - junit

Hi I want to test duplication by adding same fixture more than twice. It could be the code below:
#Test(expected=DuplicationException.class)
public void saveFailedWithDuplicatedAccount(){
memberServiceImpl.save(member);
memberServiceImpl.save(member);
}
but I don't know how to deal with Mockito coding - like using when(), verify(). Since I am new to mockito, and I have got nothing found in the Google, so is there any example code to check duplicating addition?

You need to save state somewhere.
It may be some kind of internal storage or real database.
And you can extract logic for searching duplicates and mock that.
For example:
Test(expected = DuplicationException.class)
public void saveFailedWithDuplicatedAccount() {
DuplicateService duplicateServiceMock = Mockito.mock(DuplicateService.class);
memberServiceImpl.setDuplicateService(duplicateServiceMock);
memberServiceImpl.save(member);
Mockito.when(duplicateServiceMock.isDuplicate(member)).thenReturn(true);
memberServiceImpl.save(member);
}
public class DuplicateAccountService {
public boolean isDuplicateAccount(String login) {
return false; // Some logic for find duplicates
}
}

Related

Manipulating a mocked Calendar object to return specific days

I'm using a Calendar object to determine whether or not to increase the workload of a system based on current day/hour values. Given that this object uses static methods, I'm using PowerMock to mock the static methods with the following annotations:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ Calendar.class })
The code under test is pretty simple (though my logic needs work, I know):
public void determineDefaultMaximumScans() throws ParseException{
parseTime();
Calendar cal = Calendar.getInstance();
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
System.out.println(cal.get(Calendar.DAY_OF_WEEK));
if(dayOfWeek == (Calendar.SATURDAY) || dayOfWeek == (Calendar.SUNDAY)){
setDefaultMax(calculateNewDefaultMax(getDefaultMax()));
System.out.println("defaultMax increased by 20%");
} else {
if(currentTime.after(afterHoursBegin) && currentTime.before(afterHoursEnd)){
System.out.println("Not afterhours. Maintaining current maximum.");
setDefaultMax(defaultMax);
System.out.println("Current Maximum number of scans: " + getDefaultMax());
}
}
}
My test case reads as follows:
#SuppressWarnings("static-access")
#Test
public void testDetermineMaximumScans() throws ParseException{
PowerMock.mockStatic(Calendar.class);
String beginningTime = "18:00";
String endingTime = "05:00";
mockAfterHoursBegin = parser.parse(beginningTime);
mockAfterHoursEnd = parser.parse(endingTime);
mockCurrentTime = parser.parse(parser.format(new Date()));
EasyMock.expect(Calendar.getInstance()).andReturn(mockCalendar);
EasyMock.expect(mockCalendar.get(Calendar.DAY_OF_WEEK)).andReturn(6);
EasyMock.replay(mocks);
offHourMaximumCalculator.determineDefaultMaximumScans();
EasyMock.verify(mocks);
}
As of now, all of my attempts to return a specific value result in the following assertion error. Now I vaguely understand why it's returning the default but I do not see why I can't force the value or how to get around this expectation. Mocks in general are still a frustrating mystery to me. What am I missing?
java.lang.AssertionError:
Expectation failure on verify:
Calendar.get(7): expected: 1, actual: 0
Mocks are fairly simple. But wanting to mock static methods is a big running after complexity. I generally do not recommend to mock something like a Calendar. If you do weird and complex thing with it, just encapsulate in something you can test and mock easily.
And in fact, we pretty much never use Calendar.getInstance(). It returns something according to the locale. But it's rare that you don't want a specific calendar i.e. GregorianCalendar. So just do new GregorianCalendar.
But anyway, add a protected method doing
protected Calendar newCalendar() {
return Calendar.getInstance(); // or new GregorianCalendar()
}
will take 2 minutes and then a simple partial mock will do the trick.
Finally, I also don't recommend to use Calendar. You have a much nicer API in java.util.date in Java 8.
All this said, here is how you should do it. Calendar is a system class, so you need to follow a real specific path which is explained here.
#RunWith(PowerMockRunner.class)
#PrepareForTest(Calendar.class)
public class MyTest {
#Test
public void testDetermineMaximumScans() throws ParseException {
PowerMock.mockStatic(Calendar.class);
Calendar calendar = mock(Calendar.class);
EasyMock.expect(Calendar.getInstance()).andReturn(calendar);
EasyMock.expect(calendar.get(Calendar.DAY_OF_WEEK)).andReturn(6);
// really important to replayAll to replay the static expectation
PowerMock.replayAll(calendar);
assertThat(Calendar.getInstance().get(Calendar.DAY_OF_WEEK)).isEqualTo(6);
// and verifyAll is you want to verify that the static call actually happened
PowerMock.verifyAll();
}
}

Mockito/PowerMock when....then not being invoked?

When I execute the following test, the original object is being returned and not the mock, so the real method getLevelCriteriaForLevel(level) is being executed (I observed that with the debugger). Why is that so? I'm pretty sure that this already worked yesterday and I didn't change anything there.
I already tried
#PrepareForTest({LevelCriteria.class, LevelGenerator.class})
or used the MockitoJunitRunner as I did before, but this doesn't help either.
Here is the code (generateConcreteLevel is a private method. The expected exception is only thrown when I pass this data from the mock. Otherwise it's not thrown. The test fails because the exception is not thrown, because the test doesn't use the mock object but the real object):
public class LevelGenerator
{
public void createLevel(int level)
{
generateConcreteLevel(levelCriteria.getLevelCriteriaForLevel(level));
}
private void generateConcreteLevel(LevelCriterion levelCriterion)
{
int entryGroupCount = levelCriterion.getEntryGroupCount();
int exitGroupCount = levelCriterion.getExitGroupCount();
int exitsWhileEntries = levelCriterion.getExitsWhileEntries();
int maxGroupSize = levelCriterion.getMaxGroupSize();
List<Question> questions = levelCriterion.getQuestions();
int speed = levelCriterion.getSpeed();
Range blueItemsCount = levelCriterion.getBlueItemsCount();
Range brownItemsCount = levelCriterion.getBrownItemsCount();
Range greenItemsCount = levelCriterion.getGreenItemsCount();
Range redItemsCount = levelCriterion.getRedItemsCount();
Range whiteItemsCount = levelCriterion.getWhiteItemsCount();
Range timespanBetweenGroups = levelCriterion.getTimespanBetweenGroups();
float fractionOfCarAmountToLeave = levelCriterion.getFractionOfCarAmountToLeave();
float fractionOfMinimumItemsAmountInCarParkToStartExits = levelCriterion.getFractionOfMinimumItemsAmountInCarParkToStartExits();
checkItemsFitInEntryGroups(entryGroupCount, maxGroupSize, blueItemsCount, brownItemsCount, greenItemsCount, redItemsCount, whiteItemsCount);
}
private void checkItemsFitInEntryGroups(int entryGroupCount, int maxGroupSize, Range... ranges)
{
int totalRangeCount = 0;
for (Range range : ranges)
{
totalRangeCount += range.getMaximum();
}
if (totalRangeCount > entryGroupCount * maxGroupSize)
{
throw new UnsupportedOperationException("Error in level criterion: Not enough entry groups for Items.");
}
}
}
and the test...
#RunWith(PowerMockRunner.class)
public class LevelGeneratorTest
{
#Mock
private LevelCriteria levelCriteriaMock;
#InjectMocks
private LevelGenerator levelGenerator;
#Test(expected=UnsupportedOperationException.class)
public void tooLessPositionsInEntryGroups()
{
LevelCriterion levelCriterion = new LevelCriterion.LevelCriterionBuilder()
.withBlueItemsCount(new Range(10, 10))
.withEntryGroupCount(3)
.withExitGroupCount(3)
.withMaxGroupSize(3)
.build();
when(levelCriteriaMock.getLevelCriteriaForLevel(anyInt())).thenReturn(levelCriterion);
levelGenerator.createLevel(0);
}
}
By the way: It's not an Eclipse problem, since a Maven build produces the same error.
I know that I can execute the private method with PowerMockito's Whitebox directly what I will do after refactoring, but the question is, why when...then is not working here.
Assuming your question is:
Why is the real method getLevelCriteriaForLevel(level) executed when I expect to have the mocked implementation?
I will try to demonstrate that everything works as expected fine if you reproduce it is a simple example (switch from your current workspace if you need to).
I do not have you LevelCriterion.LevelCriterionBuilder() so I simplified your test by just instantiating a LevelCriterion (empty object). This is not relevant because in my implementation I will always return an UnsupportedOperationException.
Here is how my LevelGenerator looks like. The UnsupportedOperationException is as simple as possible LevelGenerator#generateConcreteLevel(LevelCriterion).
If implemented like this:
public class LevelGenerator
{
LevelCriteria levelCriteria;
public void createLevel(int level)
{
generateConcreteLevel(levelCriteria.getLevelCriteriaForLevel(level));
}
private void generateConcreteLevel(LevelCriterion levelCriteriaForLevel)
{
throw new UnsupportedOperationException("xxx");
}
}
The test is green, using a #RunWith(MockitoJUnitRunner.class) on top of LevelGeneratorTest.
I did not used #PrepareForTest or PowerMockRunner. I have Mockito version 1.9.5.
I am sure that I have not used the real getLevelCriteriaForLevel(level) implementation, because it looks like this:
public class LevelCriteria {
public LevelCriterion getLevelCriteriaForLevel(int level) {
throw new IllegalStateException("Unexpected call");
}
}
If the real getLevelCriteriaForLevel(int) is excuted the test is red (because an IllegalStateException is thrown).
And the test is still green...
This works with pure-Mockito (version 1.9.5) approach.
You should remove all other mocking library (PowerMock, EasyMock...)
Are you sure that your static call of when(..).thenReturn(..) is the Mockito one?
Have you tried: Mockito.when(..).thenReturn(..)
I hope it helps.
PS: I have seen that you updated the question. It is a little bit unfair for me, but I am not going to update my answer once again.
I do not need the implementation detail of generateConcreteLevel(..) to illustrate that the when(..) call is working. Read my answer again. Try it in a separate workspace and you will see by yourself.
PS-2: I am using Eclipse too... Why should it be a problem? Eclipse is a great IDE.
I figured out what's wrong. Unfortunately you don't see the real problem in this question since I simplified the classes:
My real implementation of LevelGenerator got a parameterized constructor today. That's the reason why it worked yesterday but not anymore. Obviously there are mock injection problems with Mockito when not using a standard constructor.
Result: The when...then works as excpected.

Entity Framework Code First Deleting By ID Without Fetching (Generic Style)

Please tell me if this is a decent approach to deleting an Entity without fetching it given I have the ID.
I have a generic store with the following interface (I'll only show Delete):
public interface IStore : IReadOnlyStore
{
void Delete<TEntity>(TEntity entity) where TEntity : class, IEntity, new();
void SaveChanges();
}
And in the concrete Store class of that interface, here's my delete method:
public void Delete<TEntity>(TEntity entity) where TEntity : class, IEntity, new()
{
var obj = Ctx.Entry(entity);
if (obj.State == System.Data.EntityState.Detached)
{
Ctx.Set(typeof(TEntity)).Attach(obj.Entity);
}
Ctx.Set(typeof(TEntity)).Remove(obj.Entity);
}
I have tested both newing up an Entity:
Store.Delete(new Foo() { Id = request.Entity.Id });
as well as fetching an entity and then calling delete.
Through debugging, I have the desired affect on both scenarios.
I just want to make sure this is a good design and that there are no side effects to this approach.
For reference, Ctx is just the DbContext itself.
Thanks.
It's good design and doesn't have side effects :) (IMHO)
Two remarks:
I'm wondering if you could simplify your Delete method by:
public void Delete<TEntity>(TEntity entity)
where TEntity : class, IEntity, new()
{
Ctx.Entry(entity).State = EntityState.Deleted;
}
I would hope that setting the state to Deleted will attach automatically if the entity isn't already attached. But I am not sure if it works. (Let me know whether it works for attached and detached scenarios (if you should test this).)
If you have performance optimization in mind (avoiding to load the entities) don't forget that, if there are multiple entities to delete in the context, SaveChanges will still send one single DELETE statement per entity to the database. Bulk deletes with EF are quite terrible in performance and it's a terrain where going back to a SQL statements (DELETE ... WHERE ... IN ... many IDs....) sometimes makes sense (if performance matters).

Entity Framework Code First Update Does Not Update Foreign Key

I'm using EF 4.1 Code First. I have an entity defined with a property like this:
public class Publication
{
// other stuff
public virtual MailoutTemplate Template { get; set; }
}
I've configured this foreign key using fluent style like so:
modelBuilder.Entity<Publication>()
.HasOptional(p => p.Template)
.WithMany()
.Map(p => p.MapKey("MailoutTemplateID"));
I have an MVC form handler with some code in it that looks like this:
public void Handle(PublicationEditViewModel publicationEditViewModel)
{
Publication publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
publication.Template = _mailoutTemplateRepository.Get(publicationEditViewModel.Template.Id);
if (publication.Id == 0)
{
_publicationRepository.Add(publication);
}
else
{
_publicationRepository.Update(publication);
}
_unitOfWork.Commit();
}
In this case, we're updating an existing Publication entity, so we're going through the else path. When the _unitOfWork.Commit() fires, an UPDATE is sent to the database that I can see in SQL Profiler and Intellitrace, but it does NOT include the MailoutTemplateID in the update.
What's the trick to get it to actually update the Template?
Repository Code:
public virtual void Update(TEntity entity)
{
_dataContext.Entry(entity).State = EntityState.Modified;
}
public virtual TEntity Get(int id)
{
return _dbSet.Find(id);
}
UnitOfWork Code:
public void Commit()
{
_dbContext.SaveChanges();
}
depends on your repository code. :) If you were setting publication.Template while Publication was being tracked by the context, I would expect it to work. When you are disconnected and then attach (with the scenario that you have a navigation property but no explicit FK property) I'm guessing the context just doesn't have enough info to work out the details when SaveChanges is called. I'd do some experiments. 1) do an integration test where you query the pub and keep it attached to the context, then add the template, then save. 2) stick a MailOutTemplateId property on the Publicaction class and see if it works. Not suggesting #2 as a solution, just as a way of groking the behavior. I"m tempted to do this experiment, but got some other work I need to do. ;)
I found a way to make it work. The reason why I didn't initially want to have to do a Get() (aside from the extra DB hit) was that then I couldn't do this bit of AutoMapper magic to get the values:
Publication publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
However, I found another way to do the same thing that doesn't use a return value, so I updated my method like so and this works:
public void Handle(PublicationEditViewModel publicationEditViewModel)
{
Publication publication = _publicationRepository.Get(publicationEditViewModel.Id);
_mappingEngine.Map(publicationEditViewModel, publication);
// publication = Mapper.Map<PublicationEditViewModel, Publication>(publicationEditViewModel);
publication.Template = _mailoutTemplateRepository.Get(publicationEditViewModel.Template.Id);
if (publication.Id == 0)
{
_publicationRepository.Add(publication);
}
else
{
_publicationRepository.Update(publication);
}
_unitOfWork.Commit();
}
I'm injecting an IMappingEngine now into the class, and have wired it up via StructureMap like so:
For<IMappingEngine>().Use(() => Mapper.Engine);
For more on this, check out Jimmy's AutoMapper and IOC post.

Updating database row from model

I'm haing a few problems updating a row in my database using Linq2Sql.
Inside of my model I have two methods for updating and saving from my controller, which in turn receives an updated model from my view.
My model methods like like:
public void Update(Activity activity)
{
_db.Activities.InsertOnSubmit(activity);
}
public void Save()
{
_db.SubmitChanges();
}
and the code in my Controller likes like:
[HttpPost]
public ActionResult Edit(Activity activity)
{
if (ModelState.IsValid)
{
UpdateModel<Activity>(activity);
_activitiesModel.Update(activity);
_activitiesModel.Save();
}
return View(activity);
}
The problem I'm having is that this code inserts a new entry into the database, even though the model item i'm inserting-on-submit contains a primary key field.
I've also tried re-attaching the model object back to the data source but this throws an error because the item already exists.
Any pointers in the right direction will be greatly appreciated.
UPDATE:
I'm using dependancy injection to instantiate my datacontext object as follows:
IMyDataContext _db;
public ActivitiesModel(IMyDataContext db)
{
_db = db;
}
There should be an insert in case of the InsertOnSubmit method usage, this is an expected behaviour.
We recommend the Attach() method usage in your Update() method implementation. In case you have IsVersion column in the entity then everything is simple, in the other case you will have to pass the original values also to the Attach call. More information is available here in MSDN.
I fixed this issue by re-obtaining and updating my object in the Update method.
Instead of trying to re-attach or get the data context to realise it was the same object that belonged to it before I basically did as follows:
[HttpPost]
public ActionResult Edit(Activity activity)
{
Activity myActivity = activitiesModel.getActivityById(activity.id);
myActivity.name = activity.name;
myActivity.date = activity.date;
_dbContext.SubmitChanges();
return View(activity);
}
This isn't my exact code and to be more precise, I created another partial class to my datacontext and stored my update code in there.