MockMvc fails because of method invocation inside the controller method - mockito

I try to mock a controller which contains a util method inside even though I mock the util method, the mvcMock ignore the result from the when(...) and call the method again with empty parameters which lead to nullpointerexception
How I can ship the call of
when(utilMock.getOperatorsAdNameWrapper(userName, adNames)).thenReturn(roleSet);
with the mockMvc.perform?
#GetMapping(value = {"/wellbore"})
public String wellboreForm(Model model, #RequestParam("mode") String mode, HttpServletRequest request) {
Set<String> operators = new LinkedHashSet<>();
String userName = (String) request.getSession().getAttribute("userName");
Set<String> operatorsSet = (HashSet<String>) request.getSession().getAttribute("userRoles");
Set<String> operatorsAdName = util.getOperatorsAdNameWrapper(userName, operatorsSet);
operatorsAdName.forEach(adName -> {
Query query = new Query()
.setClassname(Wellbore.CLASS)
.eq(Wellbore.operatorsGroup, adName);
operators.addAll(getWellboresNameList(query));
});
model.addAttribute("wellboreDataList", operators);
model.addAttribute("wellboreData", new WellboreForm());
return "ui/selectWellbore";
}
public static Set<String> getOperatorsAdName(String userName, Set<String> operatorsAdName) {
operatorsAdName.removeIf(x -> x.equals(userName)
|| x.equals("SCOUT")
|| x.equals("GTO")
|| x.equals("KADME")
|| x.equals("offline_access")
|| x.equals("uma_authorization"));
return operatorsAdName;
}
public Set<String> getOperatorsAdNameWrapper(String userName, Set<String> operatorsAdName) {
return getOperatorsAdName(userName,operatorsAdName);
}
#Mock
private Util utilMock;
#Test
#DisplayName("GET /wellbore - Select Wellbore")
void testMockMvc() throws Exception {
HttpServletRequest req = Mockito.mock(HttpServletRequest.class);
when(req.getAttribute("userName")).thenReturn("abcd");
String userName = (String) req.getAttribute("userName");
//Here I get the correct result Result
when(utilMock.getOperatorsAdNameWrapper(userName, adNames)).thenReturn(roleSet);
//another call made here with empy parameters to utilMock.getOperatorsAdNameWrapper("", null)
mockMvc.perform(get("/wellbore").param("mode","selectWellbore")
.sessionAttr("wellboreDataList", new LinkedHashSet<>())
.sessionAttr("wellboreData", new WellboreForm())
)
.andExpect(status().isOk())
.andExpect(view().name("ui/selectWellbore"))
.andExpect(model().attribute("wellboreDataList", hasSize(2)));
}

1) In the Controller move the line:
util.getOperatorsAdNameWrapper(userName, operatorsSet);
into a package level method:
Set<String> getOperatorsAdNameWrapper(userName, operatorsSet){
return util.getOperatorsAdNameWrapper(userName, operatorsSet);
}
2) In your test use SpyBean:
#SpyBean
private Controller controllerSpy;
#Test
#DisplayName("GET /wellbore - Select Wellbore")
void testMockMvc() throws Exception {
doReturn(roleSet).when(controllerSpy).getOperatorsAdNameWrapper(userName, adNames);
The general gist is that you cannot mock a static call with vanilla Mockito. You have to refactor a bit first.

The Problem was with the Util class
since I am using mockmvc as unit testing, not as integration test by standaloneSetup
mockMvc = MockMvcBuilders
//To avoid loading springContext
.standaloneSetup(controller)
.setViewResolvers(viewResolver())
.build();
so the Util class not loaded to the context to solve this you have to option
Move the wrapper method in the util class to the service class and from there you can wrapper the static method in the Util class
Add the util class to the controller constructor

Related

How to create mockito unit tests in functions that use Mutiny.Session

After some investigation I continue to pursue a more intuitive way to mock Mutiny.Session and test my functionality.
Here the method I want to test:
public class ServiceCrud {
#Inject
Mutiny.SessionFactory mutinySessionFactory;
#Inject
MicroserviceService service;
public Uni<Service> get(#NotNull final String identifier) throws ConstraintViolationException, NotFoundException {
return mutinySessionFactory.withSession(session -> {
EntityGraph<Service> entityGraph = session.getEntityGraph(Service.class, "exampleEntityGraph");
return service.get(identifier)
.onItem().ifNull().failWith(NotFoundException::new)
.onItem().transformToUni(
microservice -> Uni.createFrom()
.item(new Service(microservice.getMsId(), microservice.getMsName())));
});
}
}
The only way I found to test was through the argument captor:
#ExtendWith(MockitoExtension.class)
public class ServiceCrudTest {
#InjectMocks
private ServiceCrud serviceCrud;
#Mock
Mutiny.SessionFactory mutinySessionFactory;
#Mock
MicroserviceService service;
#Captor
ArgumentCaptor<Function<Session, Uni<Service>>> captor;
#Mock
Session session;
#Mock
EntityGraph<Service> entityGraph;
#Test
void getTest() {
// data
String msId = "msid";
String msName = "name";
Microservice toBeReturned = new Microservice();
toBeReturned.setMsId(msId);
toBeReturned.setMsName(msName);
Service expected = new Service();
expected.setId(msId);
expected.setName(msName);
// expectation
doReturn(Uni.createFrom().item(toBeReturned))
.when(service).get(anyString());
doReturn(entityGraph).when(session)
.getEntityGraph(Mockito.eq(Service.class), Mockito.anyString());
// action
serviceCrud.get("");
// capture the function and invoke it
Mockito.verify(mutinySessionFactory).withSession(captor.capture());
Function<Session, Uni<Service>> value = captor.getValue();
Uni<Service> callback = value.apply(session);
UniAssertSubscriber<Service> subscriber = callback
.subscribe().withSubscriber(UniAssertSubscriber.create());
subscriber.assertCompleted().assertItem(expected);
}
}
Is it the only way to test? Is this the correct way to test?
Any tips will be appreciated

Spring Boot Test - Mockito - Service call return null

I'm testing a post method in my controller that only return a String and using Mockito to mock the service call. My problem is that when the service method is called on controller it return null.
#RunWith(SpringRunner.class)
#WebMvcTest(ProcessGroupController.class)
public class ProcessGroupRestControllerTest {
.............
#Test
public void givenAllNifiArguments_whenImportProcessGroup_thenReturnJsonOk() throws Exception {
NiFiArguments niFiArguments = NiFiArguments.builder()......flowVersion("3").build();
String expected = "1689d61b-624d-4574-823d-f1b4755882e1";
String json = mapper.writeValueAsString(niFiArguments);
//Mock service call
when(nifiService.importProcessGroup(niFiArguments)).thenReturn(expected);
mvc.perform(post("/nifi/pg-import").contentType(MediaType.APPLICATION_JSON).content(json))
.andExpect(status().isCreated())......);
}
The controller:
#PostMapping("/pg-import")
public ResponseEntity<String> importProcessGroup(#RequestBody NiFiArguments niFiArguments)
throws NiFiClientException {
log.info("Called method importFlow");
String result = nifiService.importProcessGroup(niFiArguments);
return new ResponseEntity<String>(result, HttpStatus.CREATED);
}
String result = null
I have similar tests that return a POJO and it works perfectly
As ekalin said my builder class needed to implement equals and hashcode:
#Builder
#Getter
#EqualsAndHashCode
public class NiFiArguments {
private String bucketIdentifier;
private String flowIdentifier;
private String flowVersion;
private String baseUrl;
}

Mock Projection Result Spring Data JPA

I am using spring data jpa in my spring boot project.
I am firing an JPQL query and using an projection to store the result of query.
My Projection :
public interface VeryBasicProjection {
String getTitle();
String getUrl();
}
My service calling this projection :
public List<VeryBasicDTO> getLatestData(int limit){
// Pageable for Limit
Pageable pageable = new PageRequest(0, limit);
// Get Data from DB
List<VeryBasicProjection> latestData = tableRepository.getLatestData("live", 2,pageable);
List<VeryBasicDTO> responseDTO = new ArrayList<>();
// Map Projection to DTO
for(VeryBasicProjection veryBasicProjection : latestData){
VeryBasicDTO veryBasicDTO = new VeryBasicDTO();
veryBasicDTO.buildDTO(veryBasicProjection);
responseDTO.add(veryBasicDTO);
}
return responseDTO;
}
Now I want to test this service using Mockito(Unit Test Case)
I am mocking the call to repository
using when and thenReturn.
My question is how do I mock the result of repository? What should be in thenReturn? I mean how do I create instance of projection and setData to it?
If you want to create an instance of your projection without creating a class implementing the interface, you can use SpelAwareProxyProjectionFactory.
import org.springframework.data.projection.ProjectionFactory;
import org.springframework.data.projection.SpelAwareProxyProjectionFactory;
// ...
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
VeryBasicProjection projection = factory.createProjection(VeryBasicProjection.class);
projection.setTitle("theTitle");
projection.setUrl("theUrl");
You also need to add setters in your projection:
public interface VeryBasicProjection {
String getTitle();
String getUrl();
void setTitle(String title);
void setUrl(String url);
}
Source: https://github.com/spring-projects/spring-data-examples/blob/master/rest/projections/src/test/java/example/springdata/rest/projections/SimpleProjectionTests.java
This is the simplest way to mock projections in TEST
VeryBasicProjection VeryBasicProjection = new VeryBasicProjection() {
String getTitle() {
return "Title";
}
String getUrl() {
return "url";
}
};
As an addition to Nis' answer:
If the interface doesn't have setters, the projection can be initialized with a map:
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
Map<String, String> map = Map.of(
"title", "theTitle",
"url", "theUrl"
);
VeryBasicProjection projection = factory.createProjection(VeryBasicProjection.class, map);
We have implemented the same stuff in below way
First mocked the two type of objects:
#Mock
private EntityManager em;
#Mock
private DemoProjectRepo demoProjectRepo;
My demoProjectRepo.findByAll returns List<DemoProjectDevices>
DemoProjectDevices device1 = new DemoProjectDevices();
device1.setAcctNbr("2365897412236589");
device1.setdeviceSeq(new BigDecimal(1));
device1.setCrteTms("2017-07-29 01:21:44.910807");
List<DemoProjectDevices> demoProjectDevices = new ArrayList<DemoProjectDevices>();
demoProjectDevices.add(device1);
For the mock when and thenReturn:
Mockito.when(demoProjectRepo.findByAll("2365897412236589", em))
.thenReturn(demoProjectDevices);
In your projection interface you need to add setters for the values you have getters for.
So when you have a concrete class implementing the projection interface you can add the values to that class so you might have something along these lines:
public interface VeryBasicProjection {
String getTitle();
String getUrl();
void setTitle(String title);
void setUrl(String url);
}
public class VeryBasicProjectionImpl implements VeryBasicProjection{
//add implementing methods
}
////
#Mock
Repository tableRepo;
#InjectMocks
ClassUnderTest c;
#Test
public void test(){
// Pageable for Limit
Pageable pageable = new PageRequest(0, limit);
VeryBasicProjection vbp = new VeryBasicProjectionImpl();
// add data to object here using the setters
List<VeryBasicProjection> projList = new ArrayList<>()
//add objects created
when(tableRepo.getLatestData("live", 2, pageable)).thenReturn(projList));
}

How to Mock repository calls ATG

Can we use Mockito to write tests for methods which implements repository calls? For example below method is using Named query to get eBooks from a Book Repository -
public RepositoryItem[] getEBooks(DynamoHttpServletRequest request) {
RepositoryItem[] results = null;
Repository rep = (Repository) request.resolveName("/atg/products/BookRepository");
try {
RepositoryItemDescriptor desc = rep.getItemDescriptor("Book");
RepositoryView view = desc.getRepositoryView();
if (view instanceof NamedQueryView) {
NamedQueryView nameView = (NamedQueryView) view;
ParameterSupportView pSupportView = (ParameterSupportView) view;
String queryName = "GetBooks";
Query namedQuery = nameView.getNamedQuery(queryName);
Object[] params = { "ebook" }; //book type
results = pSupportView.executeQuery(namedQuery, params);
}
} catch (RepositoryException e) {
logError(e.getMessage());
}
return results;
}
Thanks.
Yes you can. The question is though are you testing YOUR code or ATG in this instance?
Assuming your method above is contained in a class called GetBooks your test could look something like this:
#InjectMocks private GetBooks testObj;
#Mock private DynamoHttpServletRequest requestMock;
#Mock private Repository bookRepositoryMock;
#Mock private RepositoryItemDescriptor bookRepositoryItemDescriptorMock;
#Mock private GSAView bookRepositoryViewMock; //The only oddity here but GSAView is the common denominator for NamedQueryView and ParameterSupportView
#Mock private Query namedQueryMock;
#Mock private RepositoryItem resultRepositoryItem1, resultRepositoryItem2;
#BeforeMethod(groups = { "unit" })
public void setup() throws Exception {
testObj = new GetBooks();
MockitoAnnotations.initMocks(this);
Mockito.when(requestMock.resolveName("/atg/products/BookRepository")).thenReturn(bookRepositoryMock);
Mockito.when(bookRepositoryMock.getItemDescriptor("Book")).thenReturn(bookRepositoryItemDescriptorMock);
Mockito.when(bookRepositoryItemDescriptorMock.getRepositoryView()).thenReturn(bookRepositoryViewMock);
Mockito.when(bookRepositoryViewMock.getNamedQuery("GetBooks")).thenReturn(namedQueryMock);
List<RepositoryItem> resultArrayList = new ArrayList<RepositoryItem>();
resultArrayList.add(resultRepositoryItem1);
resultArrayList.add(resultRepositoryItem2);
Object[] params = { "ebook" }; //It may be simpler to test if this was a constant
Mockito.when(bookRepositoryViewMock.executeQuery(namedQueryMock, params)).thenReturn(resultArrayList.toArray(new RepositoryItem[resultArrayList.size()]));
}
#Test(groups = { "unit" })
public void testGetEBooks()throws Exception{
RepositoryItem[] result = testObj.getEBooks(requestMock);
Assert.assertTrue(result.length == 2); //What do you want to test?
}
This gives a greenbar when executed via TestNG. But what are you really testing here?
On a separate note. You should really use (protected) constants more since you'll then be able to use them in the package scope of your Mockito tests.

Moq: Verifying protected method on abstract class is called

This is my test
[TestClass]
public class RepositoryTests
{
private APurchaseOrderRepository _repository;
[TestInitialize]
public void TestInitialize()
{
_repository = new FakePurchaseOrderRepository();
}
[TestMethod]
public void RepositoryGetPurchaseOrdersForStoreCallsValidatePurchaseOrders()
{
var store = new Store();
var mockRepo = new Mock<APurchaseOrderRepository>();
mockRepo.Protected().Setup("ValidatePurchaseOrders", ItExpr.IsAny<List<PurchaseOrder>>());
_repository.GetPurchaseOrders(store);
mockRepo.Protected().Verify("ValidatePurchaseOrders", Times.Once(), ItExpr.IsAny<List<PurchaseOrder>>());
}
}
APurchaseOrderRepository and it's interface look like this
public interface IPurchaseOrderRepository
{
List<PurchaseOrder> GetPurchaseOrders(Store store);
}
public abstract class APurchaseOrderRepository : IPurchaseOrderRepository
{
public abstract List<PurchaseOrder> GetPurchaseOrders(Store store);
protected virtual bool ValidatePurchaseOrders(List<PurchaseOrder> purchaseOrders)
{
return true;
}
}
And my Fake
public class FakePurchaseOrderRepository : APurchaseOrderRepository
{
public override List<PurchaseOrder> GetPurchaseOrders(Store store)
{
var purchaseOrders = new List<PurchaseOrder>();
ValidatePurchaseOrders(purchaseOrders);
return purchaseOrders;
}
}
However, my test fails with:
Test method
PreSwapTests.RepositoryTests.RepositoryGetPurchaseOrdersForStoreCallsValidatePurchaseOrders
threw exception: Moq.MockException: Expected invocation on the mock
once, but was 0 times: mock =>
mock.ValidatePurchaseOrders(It.IsAny())
Configured setups: mock =>
mock.ValidatePurchaseOrders(It.IsAny()), Times.Never No
invocations performed.
What am I doing wrong?
Notes:
Moq.4.0.10827
Update:
I think it is this line mockRepo.Protected().Setup("ValidatePurchaseOrders");, because I need to add the parameters to it as a second argument, but I can't seem to get it correct.
Update 2:
Made some modifications, now it compiles, but isn't counting correctly...or something, error message and code are both updated above.
Realized I was doing this all wrong, changed my objects to work with this test
[TestMethod]
public void RepositoryGetPurchaseOrdersForStoreCallsValidatePurchaseOrders()
{
var store = new Store();
var mockPurchaseOrderProvider = new Mock<IPurchaseOrderProvider>();
var mockPurchaseOrderValidator = new Mock<IPurchaseOrderValidator>();
var purchaseOrderRepository = new PurchaseOrderRepository(mockPurchaseOrderProvider.Object, mockPurchaseOrderValidator.Object);
mockPurchaseOrderValidator.Setup(x => x.ValidatePurchaseOrders(It.IsAny<List<PurchaseOrder>>()));
purchaseOrderRepository.GetPurchaseOrders(store);
mockPurchaseOrderValidator.Verify(x => x.ValidatePurchaseOrders(It.IsAny<List<PurchaseOrder>>()), Times.Once());
}
This is a much better structure now I think.
It's because ValidatePurchaseOrders is not in your IPurchaseOrderRepository interface.
The repository is declared as private IPurchaseOrderRepository _repository; so it can only see what is in the interface.

Resources