How to mock my service using Mockito framework - java

Hello I have struglling write a mock test according to my following method below;
my code below;
#Component
public class CodeConfigBuilder {
#Value("${promoConfig.prefix.length}")
private Integer prefixLength;
public void validateRequestAndSetDefaults(PromoRequest promoRequest) {
prefixAndPostFixControlAccordingToLength(promoRequest);
}
private void prefixAndPostFixControlAccordingToLength(PromoRequest promoRequest) {
if (promoRequest.getPostfix() != null) {
int lengthControl = prefixLength + promoRequest.getPostfix().length();
if (lengthControl >= promoRequest.getLength()) {
throw new BadRequestException(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT);
}
}
}
}
my yml configuration below;
#========= Promo Config ========== #
promoConfig:
prefix:
length: 3
my service below;
public void validateRequest(PromoRequest promoRequest) {
codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
}
I have a created PropertySourceResolver class
#Component
#Getter
public class PropertySourceResolver {
private int prefixLength = 3;
and my test class below;
#RunWith(MockitoJUnitRunner.class)
class CodeConfigBuilderTest {
#MockBean
private PropertySourceResolver propertySourceResolver = new PropertySourceResolver();
#InjectMocks
private PromoRequest promoRequest = new PromoRequest();
#InjectMocks
private PromoService Service;
#Before
public void init() {
promoRequest.setPrefix("ABC");
promoRequest.setPostfix("ABCDABCD");
promoRequest.setQuantity(10);
promoRequest.setLength(12);
promoRequest.setCharset("ABCDEF");
}
#Test
public void prefixAndPostFixControl_accordingToLength_for_Succeed() {
int lengthControl = promoRequest.getPrefix().length() + promoRequest.getPostfix().length();
if (lengthControl >= promoRequest.getLength()) {
Assert.assertTrue(false);
}
}
I like to change my code according to test scenarios like ; when ... then return any idea? thank you.

To make this simpler and better organize your code, abstract away the complexity of injecting the configurations by creating the following class:
#ConfigurationProperties(prefix = "promoConfig.prefix")
public class PromoPrefixConfiguration {
private Integer length;
public Integer getLength() {
return length;
}
}
Then, you should make this a dependency for CodeConfigBuilder:
#Component
public class CodeConfigBuilder {
private Integer prefixLength;
public CodeConfigBuilder(PromoPrefixConfiguration promoPrefixConfiguration) {
this.prefixLength = promoPrefixConfiguration.getLength();
}
public void validateRequestAndSetDefaults(PromoRequest promoRequest) {
prefixAndPostFixControlAccordingToLength(promoRequest);
}
private void prefixAndPostFixControlAccordingToLength(PromoRequest promoRequest) {
if (promoRequest.getPostfix() != null) {
int lengthControl = prefixLength + promoRequest.getPostfix().length();
if (lengthControl >= promoRequest.getLength()) {
throw new BadRequestException(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT);
}
}
}
}
Now, in order to test this class you have to do it with three tests:
Test that PromoRequest is valid because postfix is null;
Test that PromoRequest is valid because length is valid;
Test that PromoRequest is invalid because length is not valid;
They would be something like the following:
class CodeConfigBuilderTest {
private PromoPrefixConfiguration promoPrefixConfiguration = new PromoPrefixConfiguration(10);
private CodeConfigBuilder codeConfigBuilder = new CodeConfigBuilder(promoPrefixConfiguration);
#Test
public void promoRequestIsValidGivenNullPostfix() {
// Arrange
PromoRequest promoRequest = new PromoRequest();
promoRequest.setPostfix(null);
// Act
codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
}
#Test
public void promoRequestIsValidGivenValidPrefixPlusPostfixLength() {
// Arrange
PromoRequest promoRequest = new PromoRequest();
promoRequest.setPostfix("ABCD");
promoRequest.setLength(15);
// Act
codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
}
#Test(expected = BadRequestException.class)
public void promoRequestIsInvalidGivenInvalidPrefixPlusPostfixLength() {
// Arrange
PromoRequest promoRequest = new PromoRequest();
promoRequest.setPostfix("ABCDEFGH");
promoRequest.setLength(15);
// Act
codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
}
}
If you are using JUnit 5, you could replace the last test with the following one to easily assert the exception message:
#Test
public void promoRequestIsInvalidGivenInvalidPrefixPlusPostfixLength() {
// Arrange
PromoRequest promoRequest = new PromoRequest();
promoRequest.setPrefix("ABCDEFG");
promoRequest.setPostfix("HIJKLMN");
// Act
Exception exception = assertThrows(BadRequestException.class, () -> {
codeConfigBuilder.validateRequestAndSetDefaults(promoRequest);
});
// Assert
String exceptionMessage = exception.getMessage();
assertTrue(exceptionMessage.equals(Constant.ClientConstants.THE_SUM_OF_PREFIX_AND_POSTFIX_CAN_NOT_BE_GREATER_THAN_LENGHT));
}
P.S.: do you mean suffix instead of postfix?

Related

Return to the list of a repository in Controller

I'm trying to return a list that is inside a Repository in my controller, but I'm not getting it. Could someone help me?
This is a RESTapi for an ATM project that I am doing for training my code. I'm using Spring Boot, Java, JUnit and Mockito. The dispenser starts with some values, however when calling the GET method, some notes are removed.
Repository
I created a list here, but I can't call it from the controller like a made with other repositories. The dispenser is created
#Repository
public class DispenserRepository {
private List<Cedula> notasDisponiveis;
public DispenserRepository() {
notasDisponiveis = new ArrayList<>();
notasDisponiveis.add(new Cedula(5, TipoNota.NOTAS_100));
notasDisponiveis.add(new Cedula(7, TipoNota.NOTAS_50));
notasDisponiveis.add(new Cedula(2, TipoNota.NOTAS_20));
notasDisponiveis.add(new Cedula(5, TipoNota.NOTAS_10));
}
public List<Cedula> buscarNotasDispenser() {
return notasDisponiveis;
}
}
SaqueService
#Service
public class SaqueService {
private static final Logger LOGGER = LoggerFactory.getLogger(SaqueService.class);
private final DispenserService dispenser;
public SaqueService(DispenserService dispenser) {
this.dispenser = dispenser;
}
public List<CedulaDTO> sacarCedulas(Integer valor) throws ValorIndisponivelException, NumeroDeNotasIndisponivelException {
List<CedulaDTO> cedulaDTOSList = buscarDistribuicaoDeCedulas(valor);
atualizarDispenser(cedulaDTOSList);
return cedulaDTOSList;
}
DispenserService
#Service
public class DispenserService {
private List<Cedula> notasDisponiveis;
private final DispenserRepository dispenserRepository;
public DispenserService(DispenserRepository dispenserRepository) {
this.dispenserRepository = dispenserRepository;
}
private void buscarNotasDispenser() {
notasDisponiveis = dispenserRepository.buscarNotasDispenser();
}
public Optional<Cedula> buscarCedulaDoTipo(TipoNota tipoNota) {
if (notasDisponiveis == null || notasDisponiveis.isEmpty()) {
buscarNotasDispenser();
}
return notasDisponiveis
.stream()
.filter(cedula -> cedula.getNota().equals(tipoNota))
.findFirst();
}
public void atualizarRetiraDeCedulas(TipoNota tipoNota, Integer quantidade) throws CedulaIndisponivelException, NumeroDeNotasIndisponivelException {
Optional<Cedula> cedulaOptional = buscarCedulaDoTipo(tipoNota);
if (cedulaOptional.isPresent()) {
cedulaOptional.get().retirarEstoque(quantidade);
} else {
throw new CedulaIndisponivelException("Cedula não encontrada!");
}
}
public List<Cedula> buscarNotasEmEstoque() {
if (notasDisponiveis == null || notasDisponiveis.isEmpty()) {
buscarNotasDispenser();
}
return notasDisponiveis
.stream()
.filter(cedula -> cedula.getQuantidadeDisponivel() > 0)
.collect(Collectors.toList());
}
}
Model
#Getter
#EqualsAndHashCode
public class Cedula {
private Integer quantidadeDisponivel;
private TipoNota nota;
public Cedula(Integer quantidadeDisponivel, TipoNota nota) {
this.quantidadeDisponivel = quantidadeDisponivel;
this.nota = nota;
}
public void retirarEstoque(Integer quantidade) throws NumeroDeNotasIndisponivelException {
if (quantidadeDisponivel < quantidade) {
throw new NumeroDeNotasIndisponivelException("Número de notas indisponível!");
}
quantidadeDisponivel = quantidadeDisponivel - quantidade;
}
}
Controller
#CrossOrigin
#RestController
#RequestMapping("/sacar")
public class SaqueController {
private final SaqueService saqueService;
public SaqueController(SaqueService saqueService) {
this.saqueService = saqueService;
}
#ResponseStatus(HttpStatus.OK)
#GetMapping("/{valor}")
public ResponseEntity<?> retornaQuantidadeDeNotas(#PathVariable("valor") Integer valor) throws ValorIndisponivelException, NumeroDeNotasIndisponivelException {
return new ResponseEntity<>(saqueService.sacarCedulas(valor), HttpStatus.OK);
}
}

Unit test with JUnit 5

Hi all i receive Nullpointer when trying to execute this unit test.I want to test e class which receive 3 parameters and returns a string. I think i need to make #Before or something else but it didn't works. Do you have suggestions...Thanks !
public class UrlConstructorTest {
private UrlConstructor urlConstructor;
#Before
public void setUp() {
urlConstructor = new UrlConstructor();
}
public static final String TEST_UPDATE_MANIFEST_SR = "/packages/proxyId/test/test1/123/test3/test_test";
#Test
public void constructUpdateManifestSrInSasTokenTest() {
String result = urlConstructor.composeDeviceRegistrationUrl("test","test123","test");
System.out.println(result);
assertNotNull(result);
assertEquals(TEST, result);
}
}
UrlConstructor is define like this:
#Component
public class UrlConstructor {
And this is the method in this class:
public String composeDUrl(String deviceId, String scopeId) {
return String.format(Constants.socpe, tes, test);
}
In Junit5, you should be using #BeforeEach. Or you can get rid of that setUp method completely.
public class UrlConstructorTest {
private final UrlConstructor urlConstructor = new UrlConstructor();
public static final String TEST_SR = "/packages/proxyId/testID/product/testscope/testcomponent/coomponent_up";
#Test
public void constructTest() {
String result = urlConstructor.composeDeviceRegistrationUrl("testID","coomponent_up","testscope");
System.out.println(result);
assertNotNull(result);
assertEquals(TEST_SR, result);
}
}

Mockito problems and says undefinied type while ı am testing my service

I am writing unit test but I am facing an error some how. I am triyng to test my ServiceImpl just showing my entire code down below My code below;
My Service Class
#Service
public class PlaneServiceImpl implements PlaneCallerService {
private final PlaneFactory planeFactory;
public PlaneServiceImpl(PlaneFactory planeFactory) {
this.planeFactory = planeFactory;
}
#Override
public String getPlaneType(String planeType) {
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(planeFactory.getPlane(planeType).getType());
stringBuilder.append(" Plane has produced.");
return stringBuilder.toString();
}
Plane class down below
public interface Plane {
String getType();
}
My PlaneFactory class down below;
#Component
public class PlaneFactory {
public Plane getPlane(String planeType) {
if (StringUtils.isBlank(planeType)) {
throw new PlaneTypeNotFoundException();
}
if (planeType.equalsIgnoreCase("lightJet")) {
return new LightJet();
} else if (planeType.equalsIgnoreCase("midJet")) {
return new MidJet();
My Mock Test just down below
public class PlaneCallerServiceImplTest {
private PlaneFactory planeFactory;
private PlaneCallerService planeCallerService;
private plane plane;
#Before
public void setUp() {
planeFactory = mock(PlaneFactory.class);
planeCallerService = new PlaneCallerServiceImpl(planeFactory);
plane= mock(Plane.class);
}
#Test
public void testPlaneType() {
String planeType = "";
when(planeFactory.getPlane(planeType)).thenReturn(plane);
String result = planeCallerService.getplaneType(planeType);
assertNotNull(result);
}
}
I'm getting The method getPlane(String) is undefined for the type PlaneFactory
I am quite new for unit test and also mock test any help would be appreciate
Thank you in advanced
Your issue is that from the below statement:
when(planeFactory.getPlane(planeType)).thenReturn(plane);
you are returning a mocked response of type Plane but in that mocked response when you call Plane.getType() that method is not implemented.
You can mock the response of that too, add
when(plane.getType()).thenReturn("SOME_MOCKED_STRING");
This should start to work.
Below is the complete test class:
public class PlaneServiceImplTest {
private PlaneFactory planeFactory;
private PlaneServiceImpl planeCallerService;
#Before
public void setUp() {
planeFactory = mock(PlaneFactory.class);
planeCallerService = new PlaneServiceImpl(planeFactory);
}
#Test
public void testPlaneType() {
Plane plane = mock(Plane.class);
when(planeFactory.getPlane(anyString())).thenReturn(plane);
String result = planeCallerService.getPlaneType("Test");
assertNotNull(result);
}
}

#MockClass is not working

I am new to jmockit and trying to execute the following online example.
The #MockClass is not working. My BookStore's getBookTitle() method is calling the function of orginal class instead of the mock class.
BookStore class:
public class BookStore {
public String getBookTitle(String isbn){
return BookStoreService.getBookTitle(isbn);
}
}
BookStoreService class:
public class BookStoreService {
public static String getBookTitle(String isbn){
return "Random";
}
}
Test class:
public class BookStoreTest {
private static Map<String, String> bookMap = new HashMap<String, String>(2);
#BeforeClass
public static void setup() {
System.out.println("in setup()");
bookMap.put("0553293354", "Foundation");
bookMap.put("0836220625", "The Far Side Gallery");
}
#MockClass(realClass = BookStoreService.class)
public static class MockBookstoreService {
#Mock
public static String getBookTitle(String isbn) {
System.out.println("in getBookTitle()");
if (bookMap.containsKey(isbn)) {
return bookMap.get(isbn);
} else {
return null;
}
}
}
#Test
public void testGetBookTitle() throws Exception {
System.out.println("in testGetBookTitle()");
final String isbn = "0553293354";
final String expectedTitle = "Foundation";
BookStore store = new BookStore();
String title = store.getBookTitle(isbn);
System.out.println(title); // This prints "Random" instead of "Foundation"
Assert.assertEquals(title, expectedTitle);
}
}
PS: I am using TestNG
Using the latest stable version of jmockit you could do it like this:
#BeforeClass
public static void setup() {
System.out.println("in setup()");
bookMap.put("0553293354", "Foundation");
bookMap.put("0836220625", "The Far Side Gallery");
new MockUp<BookStoreService>() {
#Mock
public String getBookTitle(String isbn) {
System.out.println("in getBookTitle()");
if (bookMap.containsKey(isbn)) {
return bookMap.get(isbn);
} else {
return null;
}
}
};
}
Remove the obsolete block:
public static class MockBookstoreService{...}

Checking passed params in unit testing with Mockito

I am trying to write really simple test with Mockito. I wrote small piece of code:
public class FlowTests {
#Mock
Calculator mockCalc = Mockito.mock(Calculator.class);
ConsoleView mockView = Mockito.mock(ConsoleView.class);
#Test
public void a01_Test() {
final String s = "2+2*2";
Controller c = new Controller();
c.setCalc(mockCalc);
Mockito.when(mockView.getFormule()).thenReturn(s); // I am not sure if it works
c.setView(mockView);
c.handle();
// TODO check if evaluate method has been invoked with "2+2*2"
}
}
Here you can see classes associated with this test:
public class Controller {
private IView view = new ConsoleView();
private ICalculator calc = new Calculator();
Double value = null;
public void handle() {
String formule = view.getFormule();
Double value = calc.evaluate(formule);
if (value != null) {
System.out.println("Result: ");
view.appendAnswer(value);
}
}
public void setCalc(ICalculator calc) {
this.calc = calc;
}
public void setView(IView view) {
this.view = view;
}
}
public class Calculator implements ICalculator {
public double evaluate(String s) {
...
char[] formuleChar = s.toCharArray();
result = calc.eval(formuleChar);
return result;
}
}
public class ConsoleView implements IView {
public String getFormule() {
... // getting s from console
return s;
}
public void appendAnswer(double r) {
System.out.println(r);
}
}
First goal of my test is to mock function getFormule() in ConsoleView to return always String s = "2+2*2". I did it but I am not sure if it works.
The main goal is to check if method evaluate() in Calculator class has been invoked with the same String. I have no idea how to that.
I cannot modify my code. I can only write a test.
Thank you in advance for your help!
Try something like this:
// check if evaluate method has been invoked with "2+2*2"
verify(mockCalc).evaluate("2+2*2");

Categories