set up one time code for test using #beforeeach - java

So I have to create one Integration testing and I require to setup a code only once and not before each tests. I checked many articles and it seems JUnit don't provide anything which will help us to code like that. I came across one efficient way to solve this by using below structure but it didn't worked for me.
private static boolean setUpIsDone = false;
#BeforeEach
public void createGame() {
if (setUpIsDone) {
return;
}
//setupcode
setUpIsDone = true;
}
While this should work, it didn't worked for me.
My Integration test code -
public class GameServiceIntegrationTest {
#Autowired
private GameService gameService;
#Autowired
UserService userService;
private Game testGame;
private long gameId=-1;
private static boolean setUpIsDone = false;
#BeforeEach
public void createGame() {
/*
if (setUpIsDone) {
return;
}*/
User testUser = new User();
testUser.setUsername("gamer");
testUser.setPassword("123");
testUser = userService.createUser(testUser);
List<Long> playerIdList = new ArrayList<>();
playerIdList.add(testUser.getId());
gameId = gameService.createGame(playerIdList);
testGame = gameService.getExistingGame(gameId);
// setUpIsDone = true;
}
#Test
public void chooseWord(){
System.out.println("game id here1 ->"+gameId);
int chooseIndex = 1;
gameService.chooseWord(gameId,chooseIndex);
testGame = gameService.getExistingGame(gameId);
assertEquals(testGame.getWordIndex(),0);
}
I want to use gameId variable in every other test that I continue further. If I am using the current version of code, I am getting the exception that object is already created and is failing. So it seems that setup is being executed before every test and the last test value persists.
And if I uncomment the code for setupIsDone process, I am getting gameId as -1 in other test classes. So it seems that the value is not persisting after the first test.
If there is any way to save the data in setup phase for testing overcoming above problem?

How about declaring testGame as static and then checking to see if testGame == null at the top of createGame()?

Related

Mockito Junit on a reference object

I am facing a strange problem while trying to unit test my code.
Here is my code :
public class ItemService {
private OfferService offerService;
#Inject
public ItemService (OfferService offerService){
this.offerService = offerService;
}
public List<Item> buildItems(ItemInfo itemInfo) {
List<Item> items = processItem(itemInfo);
Offers<Offer> offers = fetchItemInfo(items);
// based on the object offers, do some processing
}
private Offers<Offer> fetchItemInfo(List<Item> items) {
Offers<Offer> offers = new Offers<>();
// some processing here with offers.
// calling the db to fetch details
offerService.fetchInfoFromDB(offers);
return offers;
}
}
public class OfferService {
public void fetchInfoFromDB(Offers<Offer> offers) {
// fetching details from DB
// and updating the object **offers**
myDao.getDetailsById(id);
}
}
Now I have written junit to test the method buildItems()
UPDATE updating the mocks used and mock injection.
#RunWith(PowerMockRunner.class)
#PrepareForTest(ItemService.class)
public class ItemServiceTest{
#Mock private MyDAO myDao;
#Mock private OfferService offerService;
#Before
public void setUp() throws Exception {
ItemService itemService = new ItemService (offerService, myDao);
}
public void testBuildItems(){
// some code -----
itemInfo = buildItemInfo();
offerDetail = buildOfferDetail();
when(myDao.getDetailsById(Mockito.anyLong())).thenReturn(offerDetail);
// some code -----
// I need to implement some code which will actually call
// offerService.fetchInfoFromDB(offers);
// and update the --offers-- object and return it.
List<Item> items = itemService.buildItems(itemInfo);
Assert.assertNotNull(items);
}
}
I am running with coverage and I can see that the below line got executed but the actual method is not getting called :
offerService.fetchInfoFromDB(offers);
I am getting null values in offers. Then I added the below line :
doCallRealMethod().when(offerService).fetchInfoFromDB(offers);
Still the same result. The offers object is passed by reference and is getting updated after the DB call which I am mocking already. But upto that call my code is not reaching. How can I update the offers object in my junit. Please help.
Your test is calling a zero arg ItemService() constructor, not the one arg #Inject constructor you posted. Either your code won't compile, or you haven't actually shown us the code in question.
Also, you say you are mocking offerService:
You call when on myDao and not offerService,
you do not pass your mock offerService into your ItemService constructor, as in new ItemService(offerService), and
your doCallRealMethod won't work because your mock offerService won't use your mock myDao; you'll need to mock the call on offerService directly with a thenAnswer that changes the passed List<Offer>, as on my question you linked.
doAnswer(invocation -> {
((List<Offer>) invocation.getArgument(0)).add(offerDetail);
return null;
}).when(offerService).fetchInfoFromDb(any());
If you fix those three you will be considerably closer to a working test.

How to Mock LdapTemplate in Java and get full code coverage

I am trying to get full coverage on a very simple junit test using Mockito and am striking out. My disclaimer is that I am new to Mockito though what I am trying to do would seem pretty straightforward.
Note that my junit test passes, it is just that the coverage is not complete. When the test is run, the part of the method that returns true (users list is not empty) is not getting run/covered.
My questions are...
Does ldap need to get primed with any test data?
Can you simply mock ldap data?
Any insight you can offer is greatly appreciated.
Here is the method (class name = LdapRepository) being tested...
public Mono<Boolean> ldapTemplateQuery(Email email) {
Mono<Boolean> blockingWrapper = Mono.fromCallable(() -> {
List<LdapUser> users = ldapTemplate.find(query().where("cn").is(email.address()), LdapUser.class);
if (users.isEmpty()) {
return false;
} else {
return true;
}
}).onErrorResume(
original -> Mono.error(new UserNotFoundException("User not found for email " + email.address())));
return blockingWrapper.subscribeOn(Schedulers.elastic());
}
And here is the junit class...
#RunWith(MockitoJUnitRunner.class)
public class LdapUserRepositoryMockTest {
private #InjectMocks LdapUserRepository ldapUserRepository;
#Mock
private LdapTemplate ldapTemplate;
Email email = new Email("abcd#xyz.com");
User user = new User(email);
static final String password = "VGVzdEAxMjM=";
#Test
public void ldapTemplateQueryTest() {
LdapUser ldapUser = new LdapUser(user, password.toCharArray());
List<LdapUser> users = new ArrayList<>();
users.add(ldapUser);
lenient().when(ldapTemplate.find(query().where(Mockito.anyString()).is(Mockito.anyString()), LdapUser.class)).thenReturn(users);
Mono<Boolean> locked = ldapUserRepository.ldapTemplateQuery(email);
StepVerifier.create(locked).expectNext(false).verifyComplete();
}
And here is the screenshot of the coverage results...
With much help from someone, I was able to get my answer. As you will see below, it was a rather minor change to the lenient statement.
Hopefully this will be a help to someone along the way.
#RunWith(MockitoJUnitRunner.class)
public class LdapUserRepositoryMockTest {
private #InjectMocks LdapUserRepository ldapUserRepository;
#Mock
private LdapTemplate ldapTemplateMock;
Email email = new Email("abcd#xyz.com");
User user = new User(email);
static final String PASSWORD = "VGVzdEAxMjM=";
#Test
public void ldapTemplateQueryTest() {
LdapUser ldapUser = new LdapUser(user, PASSWORD.toCharArray());
List<LdapUser> users = new ArrayList<>();
users.add(ldapUser);
lenient()
.when(ldapTemplateMock.find(Mockito.any(), Mockito.eq(LdapUser.class)))
.thenReturn(users);
Mono<Boolean> locked = ldapUserRepository.checkIfAccountLocked(email);
StepVerifier.create(locked).expectNext(true).verifyComplete();
}
}

Junit - Running 1 test works, multiple fail on Assertion

I am having an issue where if I try running multiple tests of a similar type as what is shown below, the test fails on the assertTrue call. Running a test case separately or in the debugger gives the expected results though. I tried researching this obviously, and it said that maybe I wasn't cleaning up correctly, so I added the #After annotation. This Dao test is using an in-memory hsql database. I'm still not quite sure what I am doing wrong here. Any suggestions?
Thanks!
public class ConfigDaoTest
{
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigDaoTest.class);
private static final String DOC_ID="12345678";
private static final String STATUS_INDICATOR="S";
private static final String FILE_NAME="Testing.txt";
private DaoTestResources resources;
#Before
public void setUp()
{
resources = new DaoTestResources();
System.setProperty("IS_JUNIT_TEST", "TRUE");
}
#After
public void cleanUp()
{
resources = null;
}
#Test
public void testUpdateNotice() {
boolean retVal = false;
try {
retVal = new ConfigDao(ConfigurationManager.getInstance("test/resources/junit.test.properties")).updateNoticeByFileName(FILE_NAME,DOC_ID,STATUS_INDICATOR);
}catch(SQLException e) {
LOGGER.debug("ErrorText:" + e.getMessage());
assertNotNull(true);
}
assertTrue(retVal);
System.out.println("Return value: " + retVal);
assertNotNull(retVal);
}
// More tests like the above.
}
I'm not quite sure why this worked for me (if someone does know, I would love to know the technical details), but I removed cleanUp() and changed #Before to #BeforeClass, and now each of my test cases is running as expected when built with ant both from CL and Eclipse. My best guess is that there was some issue being caused by initializing the hsqldb before each test - that's what the resource class does.

Junit tests fail due shared instances (i think)

I think my problem is related to this issue:
Tests pass when run individually but not when the whole test class run
My tests all pass individually but when i run the test class, two of them fail. Debugging shows that that assertEquals is expecting different states than given in the code, mainly the states from different tests. The solution should be using a #Before or #After and do a cleanup, but i am having troubles using that becouse the instance is Autowired from Spring.
Main question: Is my thinking right and how do i 'reset' the autowired instance?
#SpringBootTest
class StatementProcessorServiceTest {
#Autowired
StatementProcessorService statementProcessorService;
private StatementProcessorInputModel setup(long id, boolean endbalanceCorrect) {
StatementProcessorInputModel statementProcessorInputModel = new StatementProcessorInputModel();
statementProcessorInputModel.startBalance = 1.00;
statementProcessorInputModel.id= id;
statementProcessorInputModel.startBalance = 1.00;
statementProcessorInputModel.mutation = 1.00;
statementProcessorInputModel.endBalance = endbalanceCorrect ? 2.00 : 1.00;
return statementProcessorInputModel;
}
#Test
void verify_with_all_good_settings()
{
StatementProcessorResponseModel sut;
sut = statementProcessorService.validate(setup(1, true));
Assert.assertEquals(sut.result, "SUCCESSFUL");
}
#Test
void verify_with_good_settings_but_duplicated_reference()
{
StatementProcessorResponseModel sutFirst = statementProcessorService.validate(setup(2, true));
Assert.assertEquals(sutFirst.result, "SUCCESSFUL");
StatementProcessorResponseModel sutSecond;
sutSecond = statementProcessorService.validate(setup(2, true));
Assert.assertEquals(sutSecond.result, "DUPLICATE_REFERENCE");
}
#Test
void verify_with_wrong_endBalance_and_good_reference()
{
StatementProcessorResponseModel sut = statementProcessorService.validate(setup(3, false));
Assert.assertEquals(sut.result, "INCORRECT_END_BALANCE");
}
#Test
void verify_with_all_wrong_settings()
{
StatementProcessorResponseModel sutFirst = statementProcessorService.validate(setup(4, true));
Assert.assertEquals(sutFirst.result, "SUCCESSFUL");
StatementProcessorResponseModel sutSecond = statementProcessorService.validate(setup(4, false));
Assert.assertEquals(sutSecond.result, "DUPLICATE_REFERENCE_INCORRECT_END_BALANCE");
}
}
Edit 1: Added Service code
#Component
public class StatementProcessorService {
private StatementProcessorResponseModel responseModel = new StatementProcessorResponseModel();
private static ArrayList<Long> usedReferences = new ArrayList<>();
public StatementProcessorResponseModel validate(StatementProcessorInputModel inputModel){
if(!validateUniqueReference(inputModel.transactionReference))
{
responseModel.errorRecords.add("account_number_of_ inCorrectEndBalance _record");
responseModel.result = "DUPLICATE_REFERENCE";
}
if(!validateMutation(inputModel))
{
responseModel.errorRecords.add("account_number_of_ inCorrectEndBalance _record");
if (!responseModel.result.isBlank()){
responseModel.result = responseModel.result + "_INCORRECT_END_BALANCE";
}
else{
responseModel.result = "INCORRECT_END_BALANCE";
}
}
if (responseModel.result.isBlank()){
responseModel.result = "SUCCESSFUL";
}
return responseModel;
}
If you mark your test cases/classes which modify the database with #Transactional then the test runner will rollback the transaction after the test.
You can refer to the reference documentation regarding test transactions.
It seems you're not using a database to store state, so it's difficult to add a complete answer without knowing how you are storing this state. Regardless StatementProcessorService must be storing state somehow, so I'll try to illustrate how you can reset this state between tests, and perhaps you can adapt it to your situation.
Starting from a basic "it's stored in memory" example
class StatementProcessorService {
// assuming you're storing state in memory for now
// here we're just creating a shared map, which is where we presume you're putting data
private Map<String, String> state = new HashMap<>();
}
The easiest way of doing this is to expose a method to reset the state from outside the StatementProcessorService.
class StatementProcessorService {
// ...
/** Reset state */
#VisibleForTesting
public void reset() { state.clear(); }
}
You could also use an injected state holder, which during tests can itself expose a reset method
class StateHolder {
// accessor/mutator methods
}
class TestStateHolder extends StateHolder {
// ...
public void reset() { ... }
}
class StatementProcessorService {
#Autowired
private StateHolder state;
}
And finally, you could just mock the StateHolder with Mockito
#SpringBootTest
class StatementProcessorServiceTest {
#MockBean StateHolder state;
}
As normal with Spring, there are a lot of ways of achieving your goal.

How to test business logic in method?

I have such method in my service layer:
public Long calculateItemsCostInShoppingCart(Long shoppingCartId) {
List<Item> items = shoppingCartRepository.findAllItems(shoppingCartId);
Long cost = 0L;
for (Item item : items) {
cost += item.getPrice();
}
return cost;
}
And I need to test calculation of summary cost of all items in list. I was thought about mockito, but it didn't work out cause mockito just create stubs, I need real entrance data and result based on them. How can do it?
// create mock
ShoppingRepository mock = mock(ShoppingRepository.class);
// define return value for method findAllItems()
when(mock.findAllItems()).thenReturn(listOf(...));
Here is an example how you can test it with Mockito:
public class SomeCalculatorTest {
#Mock
private ShoppingCartRepository shoppingCartRepository;
#InjectMocks
private SomeCalculator someCalculator = new SomeCalculator();
#Before
public void setUp() {
initMocks(this);
}
#Test
public void testEmptyItemsList() {
when(shoppingCartRepository.findAllItems(any())).thenReturn(new ArrayList<>());
final Long result = someCalculator.calculateItemsCostInShoppingCart(1L);
assertThat(result, is(0L));
}
#Test
public void testOneItemInList() {
when(shoppingCartRepository.findAllItems(any())).thenReturn(Arrays.asList(new ItemImpl(25L)));
final Long result = someCalculator.calculateItemsCostInShoppingCart(1L);
assertThat(result, is(25L));
}
#Test
public void testTwoItemInList() {
when(shoppingCartRepository.findAllItems(any())).thenReturn(Arrays.asList(new ItemImpl(25L), new ItemImpl(12L)));
final Long result = someCalculator.calculateItemsCostInShoppingCart(1L);
assertThat(result, is(37L));
}
}
Assuming that you are developing a Java web application which runs on a application server another option might be to use Arquillian (http://arquillian.org/). In a nutshell, Arquillian is a framework which allows you to test you logic in environment it will run. But it might be some work to integrate Arquillian into your project. We are using Arquillian in several projects and it works well so far. Even the Persistence module which is an Alpha version works well.
And I need to test calculation of summary cost of all items in list.
In this case, you have to isolate the shoppingCartRepository dependency that doesn't perform any calculation.
I need real entrance data and result based on them. How can do it?
It describes an integration test. In this case, don't use Mockito.
To unit test :
You have to mock the dependency and you also need a way to set it in the instance of the class under test.
A constructor is often a fine way (let calling the class under test MyService):
public MyService(ShoppingCartRepository shoppingCartRepository){
this.shoppingCartRepository = shoppingCartRepository;
}
Then, in the test you should mock ShoppingCartRepository, record a behavior for findAllItems() and pass the mock in the constructor of MyService.
#Mock
private ShoppingCartRepository shoppingCartRepositoryMock;
#Test
public void calculateItemsCostInShoppingCart(){
Long cartId = Long.valueOf(123);
// set the dependency
MyService myService = new MyService(shoppingCartRepositoryMock);
// create the mock
Mockito.when(shoppingCartRepositoryMock.findAllItems(cartId))
.thenReturn(createMockedItems());
//action
Long actualCost = myService.calculateItemsCostInShoppingCart(cartId);
// assertion
Assert.assertEquals(expectedCost, actualCost);
}
private List<Item> createMockedItems() { ... }
You can use Rest assured library for test
get Rest assured response Object, and call method for method object of list.
#BeforeClass
public static void init() {
RestAssured.baseURI = "http://localhost";
RestAssured.port = 8080;
}
#Test
public void testUserRegistration() {
Response response =
RestAssured
.given()
.get(URL_LOGIN)
.then()
.assertThat()
.statusCode(200);
Assert.assertThat(200, Matchers.is(200));
Assert.assertThat(response.getStatusCode(), Matchers.is(200));
}

Categories

Resources